因此,我正在尝试按照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"
答案 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();
}, []);