React has detected a change in the order of Hooks --- When using Context within a Hook

Viewed 41

So basically I'm having problems with a useUser custom React hook I have written. Basically, this hook queries the current user and returns the fields such as username, id, email etc. However I want to first check the context to avoid unnecessary API calls.

You can see my logic below, however when I then try to set the User context after a successful API call (using the dispatch), I get the "Order of Hooks" error. I see why it's complaining but I don't know the correct solution to solve this. Can anyone see how to structure my hook so that I can still achieve what I'm trying to do?

Any advice would be much appreciated.

export const useUser = () => {

  // first check if user exists in context. This prevents unnecessary API queries on every page load
  const {
    state: { userInfo },
    dispatch,
  } = useUserContext();

  if (userInfo) return userInfo

  // if userInfo doesn't exist on context state, only then query the server.
  const [info, setInfo] = useState<UserType>()

  const { data: user, isLoading, error } = useMeQuery(gqlClient, { }, { 
    onSuccess: (data) => {
      // onSuccess, set the context state to the user
      dispatch({
          type: "SET_USER_INFO",
          payload: data.me,
        });
    },
    enabled: !userInfo
  })

  useEffect(() => {
    if (isLoading) return

    if (error || !user?.me) {
      return setInfo(undefined)
    }
    const { email, id, username, role } = user?.me as UserType
  
    setInfo({
      id,
      email,
      username,
      role,
    })
  }, [isLoading, user, error])

  return info
}
1 Answers

You're returning a hook conditionally because you're calling a useEffect hook below

if (userInfo) return userInfo

condition, it break one of the react hooks rules:

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns.

More information can be found below: https://reactjs.org/docs/hooks-rules.html

Related