JaeLeeSo
JaeLeeSo

Reputation: 263

Change in the order of hooks error from context to useEffect

ERROR Warning: React has detected a change in the order of Hooks called by AuthPage. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks

Previous render Next Render
useContext useContext
useContext useContext
useState useState
useEffect useEffect
useContext useEffect

The code:

import React, { useContext, useEffect, useState } from 'react';
import { Keyboard } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { getCredentials } from '../util/Storage';
import { OrderContext } from '../OrderContext';
import { UserContext } from '../UserContext';

const AuthPage = ({ navigation }) => {
  const userContext = useContext(UserContext);
  const orderContext = useContext(OrderContext);
  const [isKeyboardVisible, setKeyboardVisibile] = useState(false);
  useEffect(() => {
    const getCreds = async () => {
      const c = await getCredentials();
      if (c) {
        navigation.replace('Home' : 'StartWizard');
      }
    };
    getCreds();
  }, []);

  const keyboardDidShow = () => {
    setKeyboardVisibile(true);
  };

  const keyboardDidHide = () => {
    setKeyboardVisibile(false);
  };

  useEffect(() => {
    Keyboard.addListener('keyboardDidShow', keyboardDidShow);
    Keyboard.addListener('keyboardDidHide', keyboardDidHide);

    return () => {
      Keyboard.removeListener('keyboardDidShow', keyboardDidShow);
      Keyboard.removeListener('keyboardDidHide', keyboardDidHide);
    };
  }, []);

  if (!global.navigation) {
    global.navigation = useNavigation();
  }

  return (
    <AuthView ... />
      }}
    />
  );
};

const Auth = ({ navigation }) => <AuthPage navigation={navigation} />;
export default Auth;

Why is the order changing and how do I correct this behavior?

Upvotes: 1

Views: 963

Answers (2)

Adam Jeliński
Adam Jeliński

Reputation: 1788

React always expects the same hooks to be called, no matter what values your variables have.

In this case, you conditionally call the useNavigation() hook, which completely messes up what React wants.

To fix it, just store the value returned by the hook in a temporary variable:

const currentNavigation = useNavigation();
if (!global.navigation) {
    global.navigation = currentNavigation;
}

or overwrite the global.navigation unconditionally if it's not a problem

global.navigation = useNavigation();

I strongly recommend reading up on the rules of hooks, so you can avoid errors like this in the future.

Upvotes: 0

GBourke
GBourke

Reputation: 1963

  if (!global.navigation) {
    global.navigation = useNavigation();
  }

Never conditionally call a hook. Its a rule of hooks

Upvotes: 0

Related Questions