什么是无限递归?

时间:2020-06-21 04:21:15

标签: react-native react-navigation react-navigation-v5

因此,我正在尝试按照React导航教程进行身份验证流程https://reactnavigation.org/docs/auth-flow/

但是由于某种原因,它会导致无限次重新渲染,屏幕会像疯了似的闪烁,而且我不知道为什么除了useEffect中的调度只是更新每个渲染器的状态外,据我所知不应该发生的。

import React from "react"
import { NavigationContainer, NavigationContainerRef } from "@react-navigation/native"

import { createNativeStackNavigator } from "react-native-screens/native-stack"
import { PrimaryNavigator, AuthNavigator, DrawerNavigator } from "./primary-navigator"
import { SplashScreen } from "../screens/splash-screen"
import AsyncStorage from "@react-native-community/async-storage"

export type RootParamList = {
  primaryStack: undefined,
  authStack: undefined,
  splashScreen: undefined,
}

const Stack = createNativeStackNavigator<RootParamList>()

const RootStack = () => {
  const AuthContext = React.createContext()

  const [state, dispatch] = React.useReducer(
    (prevState, action) => {
      switch (action.type) {
        case 'RESTORE_TOKEN':
          return {
            ...prevState,
            userToken: action.token,
            isLoading: false,
          }
        case 'SIGN_IN':
          return {
            ...prevState,
            isSignout: false,
            userToken: action.token,
          }
        case 'SIGN_OUT':
          return {
            ...prevState,
            isSignout: true,
            userToken: null,
          }
      }
    },
    {
      isLoading: true,
      isSignout: false,
      userToken: null,
    }
  )

  React.useEffect(() => {
    const bootstrapAsync = async () => {
      let userToken

      try {
        userToken = await AsyncStorage.getItem('userToken')
        console.log(userToken)
      } catch (e) {
        console.log(e)
      }

      // After restoring token, we may need to validate it in production apps

      // This will switch to the App screen or Auth screen and this loading
      // screen will be unmounted and thrown away.

      dispatch({ type: 'RESTORE_TOKEN', token: userToken })
    }

    bootstrapAsync()
  })

  const authContext = React.useMemo(
    () => ({
      signIn: async data => {
        // In a production app, we need to send some data (usually username, password) to server and get a token
        // We will also need to handle errors if sign in failed
        // After getting token, we need to persist the token using `AsyncStorage`
        // In the example, we'll use a dummy token

        dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' })
      },
      signOut: () => dispatch({ type: 'SIGN_OUT' }),
      signUp: async data => {
        // In a production app, we need to send user data to server and get a token
        // We will also need to handle errors if sign up failed
        // After getting token, we need to persist the token using `AsyncStorage`
        // In the example, we'll use a dummy token

        dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' })
      },
    }), [])

  return (
    <AuthContext.Provider value={authContext}>
      <Stack.Navigator
        screenOptions={{
          headerShown: false,
          gestureEnabled: true,

          stackPresentation: "modal",
        }}
      >

        { state.userToken == null
          ? <Stack.Screen
            name="authStack"
            component={AuthNavigator}
            options={{
              headerShown: false
            }}
          />
          : <Stack.Screen
            name="primaryStack"
            component={DrawerNavigator}
            options={{
              headerShown: false,
            }}
          />
        }

      </Stack.Navigator>
    </AuthContext.Provider>
  )
}

export const RootNavigator = React.forwardRef<
  NavigationContainerRef,
  Partial<React.ComponentProps<typeof NavigationContainer>>
>((props, ref) => {
  return (
    <NavigationContainer {...props} ref={ref}>
      <RootStack />
    </NavigationContainer>
  )
})

RootNavigator.displayName = "RootNavigator"

1 个答案:

答案 0 :(得分:1)

您错过了教程中提供的依赖项[[]”。当您为useEffect提供依赖项时,它将仅在依赖项发生更改时运行。您似乎错过了本教程中提供的内容。

这是来自教程

 React.useEffect(() => {
    // Fetch the token from storage then navigate to our appropriate place
    const bootstrapAsync = async () => {
      let userToken;

      try {
        userToken = await AsyncStorage.getItem('userToken');
      } catch (e) {
        // Restoring token failed
      }

      // After restoring token, we may need to validate it in production apps

      // This will switch to the App screen or Auth screen and this loading
      // screen will be unmounted and thrown away.
      dispatch({ type: 'RESTORE_TOKEN', token: userToken });
    };

    bootstrapAsync();
  }, []);
相关问题