Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call React hook depending on Promise

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?

like image 547
ztefanie Avatar asked Oct 16 '25 03:10

ztefanie


1 Answers

You need to either modify the useLoadRoot hook or wrap that logic in a child component. Hooks don't allow conditional usage.

Route 1: Rewrite 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).

Route 2: Conditional child component

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);

  ...
}
like image 134
Asen Mitrev Avatar answered Oct 17 '25 17:10

Asen Mitrev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!