javascript - React har upptäckt en förändring i ordningen på Hooks som anropas av Navigation


Jag har verkligen svårt att lista ut var mitt problem ligger här, jag har ändrat mycket kod nyligen och nu möts jag av detta problem

   ERROR  Warning: React has detected a change in the order of Hooks called by Navigation. 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
   ------------------------------------------------------
1. useContext                 useContext
2. undefined                  useRef
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    in Navigation (at App.tsx:96)
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:217)
    in AnimatedComponent (at createAnimatedComponent.js:278)
    in AnimatedComponentWrapper (at createAnimatableComponent.js:599)
    in withAnimatable(View) (at App.tsx:89)
    in App (at mobile/index.js:28)
    in HeadlessCheck (at renderApplication.js:47)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:107)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:134)
    in AppContainer (at renderApplication.js:40)

Förmodligen syftar detta på min Navigation-klass, som jag kommer att dela nedan, jag är inte särskilt insatt i konceptet bakom hooks och detta problem förvirrar mig

import * as React from 'react';
import { View } from 'react-native';
import { NavigationContainer, NavigationContainerRef } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { useStore } from '_src/store';
import { logScreenView } from '_utils/analytics';

import { SharedStackParamList } from './shared/SharedStack';
import { getSharedScreens } from './shared/Shared.screens';

import ErrorBoundary from '../components/atoms/ErrorBoundary';
import { modalOptions } from './StackOptions';
import { BLACK } from '_styles/colors';

const SharedStack = createStackNavigator<SharedStackParamList>();

export const Navigation = () => {
  const rootStore = useStore();
  const { authStore } = rootStore;
  if (authStore.token === undefined) return null;

  const routeNameRef = React.useRef<string>();
  const navigationRef = React.useRef<NavigationContainerRef>();

  function onReady() {
    routeNameRef.current = navigationRef.current.getCurrentRoute().name;
  }

  function onStateChange() {
    const previousRouteName = routeNameRef?.current;
    const currentRouteName = navigationRef?.current?.getCurrentRoute()?.name;

    if (previousRouteName !== currentRouteName) {
      logScreenView({ screen_name: currentRouteName, screen_class: currentRouteName });
      routeNameRef.current = currentRouteName;
    }
  }

  // Return main stack
  return (
    <View style={{ flex: 1, backgroundColor: BLACK, opacity: 1 }}>
      <ErrorBoundary>
        <NavigationContainer ref={navigationRef as any} onReady={onReady} onStateChange={onStateChange}>
          <SharedStack.Navigator screenOptions={modalOptions} mode="modal">
            {getSharedScreens().map(({ name, options, component }, i) => {
              // @ts-ignore
              return <SharedStack.Screen key={i} name={name} options={options} component={component} />;
            })}
          </SharedStack.Navigator>
        </NavigationContainer>
      </ErrorBoundary>
    </View>
  );
};

export default Navigation;

Om någon kan hjälpa mig att förstå hooks lite bättre och hjälpa mig med detta problem, skulle det vara mycket uppskattat.

Svar #1

Kolla in reglerna för hooks (sida i den gamla React-dokumentationen)

Hooks måste alltid kallas i samma ordning (så att lägga till nya hooks villkorligt är inte tillåtet). Din kod bryter mot denna regel eftersom du använder useRef-hooks efter att villkorligt ha returnerat null.

Lösningen är mycket enkel: Flytta useRef-användningarna ovanför if (authStore.token === undefined) return null; så är du klar.

Relaterade artiklar