Home > Net >  React Hooks : Conditionally call another custom hook
React Hooks : Conditionally call another custom hook

Time:10-19

I have a an async hook, which gets the user useGetUser

function useGetUser() {
  const [user, setUser] = useState(false);

  useEffect(() => {
    async function getUser() {
      const session = await Auth.currentSession();
      setUser(session);
    }

    if (!user) {
      getUser();
    }
  }, [user]);

  return user;
}

From another hook, I'm calling this hook, and only when I get the user, I want to execute the query:

function useGraphQLQuery() {
  const user = useGetUser();
  useEffect(() => {
    if (user) {
      useQuery(`blablabla`, async () =>
        request(endpoint, query, undefined, {
          authorization: user.getAccessToken().getJwtToken() || '',
        })
      );
    }
  }, [user]);
}

This code doesn't work because useQuery needs to be outside of useEffect and also because of the condition, but I need to wait for the user to be fetched...

Thank you.

CodePudding user response:

I think you should have a slightly different approach. For example , encapsulate all your routes into a component , let's call it App , in App.js. In App.js you want to use the useEffect hook to check if the user is authentificated or not, something like this:

React.useEffect(() => {
        //We refresh the access token every time the page is changed
        fetch('http://localhost:1000/refresh_token', {
            method: 'POST',
            credentials: 'include',
        }).then(async x => {
           
            const { accessToken } = await x.json()
            // we set the access token
            setAccessToken(accessToken)
            setLoading(false)
        })
    }, [])

Then , from the App component, render all your components , just like in index.js. Now you can easily use the useQuery hook in each of your components corresponding to a page .

CodePudding user response:

The useGetUser hook is a bit strange since it uses a state variable which also is being set by the effect. Since it is really easy to get unwanted effects or even infinite render loops, I would prevent that.

Since it only needs to run once on startup, you can remove the !user part and also the user dependency. I can imagine you would like this hook to be updated when the Auth service receives a session.

function useGetUser() {
  const [user, setUser] = useState(false);

  useEffect(() => {
    async function getUser() {
      const session = await Auth.currentSession();
      setUser(session);
    }
    
    getUser();
  }, []);

  return user;
}

For the useQuery hook, you can use the enabled option to prevent the useQuery from executing when set to false. You can also remove the useEffect since it's already a hook which responds to option changes.

function useGraphQLQuery() {
  const user = useGetUser();
  
  useQuery(`blablabla`, async () => request(endpoint, query, undefined, {
      authorization: user.getAccessToken().getJwtToken() || '',
  }), { enabled: !!user });
}
  • Related