[skip envinfo]
{
"private": true,
"main": "./app-entry.js",
"scripts": {
"dev": "expo start",
"prod": "expo start --no-dev"
},
"dependencies": {
"expo": "^31.0.2",
"react": "^16.7.0-alpha.2",
"react-cache": "^2.0.0-alpha.1",
"react-native": "https://github.com/expo/react-native/archive/sdk-31-with-hooks-dangerzone.tar.gz"
},
"devDependencies": {
"babel-preset-expo": "^5.0.0",
"expo-cli": "^2.6.12"
}
}
When trying to use Suspense on React Native, I am receiving a Not yet implemented issue, after the react-cache package has resolved the data.
import React, { useState, ConcurrentMode, Suspense } from "react";
import { StyleSheet, SafeAreaView, Button, Text } from "react-native";
import { unstable_createResource as createResource } from "react-cache";
const myPokemon = createResource(function fetchPokemon(name) {
const pokemonQuery = `
query ($name: String) {
pokemon(name: $name) {
id
number
name
}
}
`;
return fetch("https://graphql-pokemon.now.sh", {
method: "POST",
headers: {
"content-type": "application/json;charset=UTF-8"
},
body: JSON.stringify({
query: pokemonQuery,
variables: { name }
})
})
.then(r => r.json())
.then(response => response.data.pokemon);
});
function PokemonInfo({ pokemonName }) {
const pokemon = myPokemon.read(pokemonName);
console.log(pokemon);
return <Text>{JSON.stringify(pokemon || "Unknown", null, 2)}</Text>;
}
export default function App() {
const [pokemonName, setPokemonName] = useState(null);
const [search, setSearch] = useState(false);
return (
<SafeAreaView style={styles.container}>
<Button title="Get Pikachu" onPress={() => setPokemonName("Pikachu")} />
{pokemonName ? (
<Suspense fallback={<Text>loading...</Text>}>
<PokemonInfo pokemonName={pokemonName} />
</Suspense>
) : null}
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff",
flex: 1,
margin: 20
},
textInput: {
backgroundColor: "#eaeaea",
borderColor: "#cccccc",
borderWidth: 1,
height: 40,
padding: 10
}
});
Can you run react-native info and edit your issue to include these results under the Environment section?
If you believe this information is irrelevant to the reported issue, you may write [skip envinfo] under Environment to let us know.
Haven't used Suspense yet, but based off the docs it looks like you need to use it with React.lazy
https://reactjs.org/docs/react-api.html#reactsuspense
Today, lazy loading components is the only use case supported by <React.Suspense>
@Taylor123 not necessary, you can use Suspense not to lazy load components, but for suspending rendering when for example, making a http request.
Yes, @Taylor123 we can use react suspense functionality without react.lazy as far as in the context of web. now trying to use in react-native to which i'm facing the same issue.
Any idea if this is on the roadmap / coming any time soon?
It's working in progress, I think that soon will be stable.
Thank you React-Native Team!
I got the reproduceable demo above (minus the react-cache - did my own test cache) to work in 0.59.0-rc.3.
It's working in progress, I think that soon will be stable.
react-native/Libraries/Renderer/oss/ReactNativeRenderer-dev.js
Line 4319 in d4ce846
function unhideInstance(instance, props) {
Thank you React-Native Team!
I'm using this implementation to test my apps, and so far I could go it's working well. I'm found some troubles with expo integration.
Note: 0.59-rc was shipped with support to hooks
This should be working in the latest release - if it's not please let us know and we can re-open
Hi, I'm using react-native 0.59.5 and tried to implement Suspense but it never falls back to the fallback component
ProductsList.js
function ProductsList() {
const { navigate } = useNavigation()
const mobileNumber = useNavigationParam("mobileNumber")
const [departmentData, departmentFetching, departmentError] = useRequest(() =>
webApi.api.getCallBackDepartments()
)
const rows = getRows({ departments: departmentData ? departmentData : [] })
const handleButtonPress = department => {
navigate("SelectCallBackTimeScreen", {
mobileNumber: mobileNumber,
department: department
})
}
console.log("departmentData", !departmentData.length)
if (!departmentData.length) {
return null
}
return (
<View style={{ paddingHorizontal: 10, flex: 1 }}>
{rows.map(value => (
<View
key={shortid.generate()}
style={[styles.bodyCardRow, { marginTop: -10, marginBottom: 10 }]}
>
<View style={styles.bodyCardColumn}>
<Card
handlePress={() => handleButtonPress(departmentData[2 * value])}
name={departmentData[2 * value] ? departmentData[2 * value].name : "test"}
/>
</View>
{departmentData[2 + 2 * value] && (
<Card
handlePress={() => handleButtonPress(departmentData[1 + 2 * value])}
name={departmentData[1 + 2 * value] && departmentData[1 + 2 * value].name}
/>
)}
</View>
))}
</View>
)
}
selectAproduct.js
import React, { useEffect, Suspense, lazy } from "react"
import { connect } from "react-redux"
import { BackHandler, SafeAreaView, View } from "react-native"
import { useNavigation } from "react-navigation-hooks"
import BaseStyles from "../../Styles/App"
import CustomHeader from "../../../Components/CustomHeader"
import GoBack from "../../../Components/GoBack"
import Loader from "../../../Components/Loader"
import Text from "../../../Components/Text"
const ProductsLazy = lazy(() => import("./ProductsList"))
function SelectAProduct() {
const { pop } = useNavigation()
useEffect(() => {
const backPressed = () => {
pop()
return true
}
BackHandler.addEventListener("hardwareBackPress", backPressed)
return () => {
BackHandler.removeEventListener("hardwareBackPress", backPressed)
}
}, [pop])
return (
<View style={BaseStyles.applicationView}>
<CustomHeader
popBack={() => pop()}
left={<GoBack backScreen={"Call Me Back"} />}
heading={"Select a Product"}
/>
<Suspense fallback={<Text>loading ...</Text>}>
<ProductsLazy />
</Suspense>
<SafeAreaView />
</View>
)
}
function Loading({ departmentFetching }) {
return (
<View style={BaseStyles.applicationView}>
<Loader animating={departmentFetching} />
</View>
)
}
const mapStateToProps = state => ({
// cart: state.cart.items
})
export default connect(
mapStateToProps,
{}
)(SelectAProduct)
Most helpful comment
@Taylor123 not necessary, you can use Suspense not to lazy load components, but for suspending rendering when for example, making a http request.