Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
React native 什么是导致无限重渲染的原因?_React Native_React Navigation_React Navigation V5 - Fatal编程技术网

React native 什么是导致无限重渲染的原因?

React native 什么是导致无限重渲染的原因?,react-native,react-navigation,react-navigation-v5,React Native,React Navigation,React Navigation V5,因此,我试图遵循auth flow的react导航教程 但出于某种原因,它会导致无限重渲染,屏幕疯狂地闪烁,我不知道除了useffect中的调度之外,为什么每次渲染都会更新状态,但据我所知,这是不应该发生的 import React from "react" import { NavigationContainer, NavigationContainerRef } from "@react-navigation/native" import { cre

因此,我试图遵循auth flow的react导航教程

但出于某种原因,它会导致无限重渲染,屏幕疯狂地闪烁,我不知道除了
useffect
中的调度之外,为什么每次渲染都会更新状态,但据我所知,这是不应该发生的

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"
从“React”导入React
从“@react navigation/native”导入{NavigationContainer,NavigationContainerRef}
从“反应本机屏幕/本机堆栈”导入{createNativeStackNavigator}
从“/primary navigator”导入{PrimaryNavigator,AuthNavigator,DrawerNavigator}
从“./screens/SplashScreen”导入{SplashScreen}
从“@react native community/async storage”导入异步存储
导出类型RootParamList={
primaryStack:未定义,
authStack:未定义,
splashScreen:未定义,
}
const Stack=createNativeStackNavigator()
常量根堆栈=()=>{
const AuthContext=React.createContext()
const[state,dispatch]=React.useReducer(
(状态、动作)=>{
开关(动作类型){
案例“还原令牌”:
返回{
…国家,
userToken:action.token,
孤岛加载:false,
}
“签到”案例:
返回{
…国家,
isSignout:错,
userToken:action.token,
}
“注销”案例:
返回{
…国家,
是的,
userToken:null,
}
}
},
{
孤岛加载:是的,
isSignout:错,
userToken:null,
}
)
React.useffect(()=>{
const bootstrapAsync=async()=>{
让用户令牌
试一试{
userToken=await AsyncStorage.getItem('userToken')
日志(userToken)
}捕获(e){
控制台日志(e)
}
//还原令牌后,我们可能需要在生产应用程序中验证它
//这将切换到应用程序屏幕或身份验证屏幕,并进行此加载
//屏幕将被卸下并丢弃。
分派({type:'RESTORE_TOKEN',TOKEN:userToken})
}
bootstrapAsync()
})
const authContext=React.useMoom(
() => ({
签名:异步数据=>{
//在生产应用程序中,我们需要向服务器发送一些数据(通常是用户名、密码)并获取令牌
//如果登录失败,我们还需要处理错误
//在获得令牌之后,我们需要使用'AsyncStorage'持久化令牌`
//在本例中,我们将使用虚拟令牌
分派({type:'SIGN_IN',token:'dummy auth token'})
},
签出:()=>dispatch({type:'SIGN_OUT'}),
注册:异步数据=>{
//在生产应用程序中,我们需要将用户数据发送到服务器并获取令牌
//如果注册失败,我们还需要处理错误
//在获得令牌之后,我们需要使用'AsyncStorage'持久化令牌`
//在本例中,我们将使用虚拟令牌
分派({type:'SIGN_IN',token:'dummy auth token'})
},
}), [])
返回(
{state.userToken==null
? 
: 
}
)
}
export const RootNavigator=React.forwardRef<
NavigationContainerRef,
部分的
>((道具,参考)=>{
返回(
)
})
RootNavigator.displayName=“RootNavigator”

您错过了教程中提供的依赖项“[]”。当您向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();
  }, []);