I have an ID stored in AsyncStorage and depending on this call, I want to make a server request.
So something like this is needed:
AsyncStorage.getID().then(id => {
useLoadFromServer(id)
}
But I always struggle with getting errors about using hooks wrong. So far I tried:
// First Approach
const MyScreen = () => {
const [ID, setID] = useState()
AsyncStorage.getID()
.then(id => setID(id))
.catch(e => console.log(e))
const { data } = useLoadRoot(ID) // Not the ID from AsyncStorage is used
}
//Second Approach
const MyScreen = async () => {
const [ID, setID] = useState()
const IDPromise = AsyncStorage.getID()
const { data } = useLoadRoot(await IDPromise) // Possible Unhandled Promise Rejection
also I tried to use useEffect
, which leads to React Hooks must be called in a React function component or a custom React Hook function
The useLoadRoot-hook just calls another hook UseLoadFromEndpoint
doing the axios.get()
When trying to move the AsyncStorage-Request to the customHook, I get the same errors, as I call the useLoadFromEndpoint
-hook incorrectly, but I have to / want to reuse the UseLoadFromEndpoint-Hook. How can I achive this?
You need to either modify the useLoadRoot
hook or wrap that logic in a child component. Hooks don't allow conditional usage.
useLoadRoot
const useLoadRoot = (id) => {
const getRoot = async (rootId) => ...;
const [root, setRoot] = useState();
useEffect(() => {
if (id != undefined) {
await getRoot(id);
}
}, [id]);
return root;
}
This is just one way to achieve what you want. You can pass in an enabled property that is a boolean that allows requests only if true. This is the approach that is used in react-query, for example (see: docs).
const Parent = () => {
const [ID, setID] = useState()
useEffect(() => {
AsyncStorage.getID()
.then(id => setID(id))
.catch(e => console.log(e))
}, []);
return ID ? <WithFetchRoot rootId={ID}/> : null; //could be a loader component instead of null
}
const WithFetchRoot = (id) => {
const root = useLoadRoot(ID);
...
}