You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native导航初始页面异常排查:完成引导页后仍跳转至引导页而非登录页

Troubleshooting Your React Native Onboarding Route Issue

Let’s break down what’s going wrong and how to fix it:

1. Reducers Shouldn’t Handle Async Side Effects

Your current reducer is calling AsyncStorage.setItem directly, which is an asynchronous operation. Redux reducers must be pure, synchronous functions—side effects like async storage calls belong in thunks, not reducers. This is likely causing inconsistent state persistence.

Fix: Use an Async Thunk

Replace your onboarding slice with this, which uses a Redux Toolkit thunk to handle the async storage:

import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
import AsyncStorage from '@react-native-async-storage/async-storage'

export interface onboardingState {
  viewedOnBoarding: boolean
}

const initialState: onboardingState = {
  viewedOnBoarding: false,
}

// Async thunk to handle state update and storage
export const setOnboardingAsync = createAsyncThunk(
  'onboarding/setOnboardingAsync',
  async (value: boolean) => {
    await AsyncStorage.setItem('@onBoarding', JSON.stringify(value))
    return value
  }
)

export const onboardingSlice = createSlice({
  name: 'onboarding',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(setOnboardingAsync.fulfilled, (state, action) => {
      state.viewedOnBoarding = action.payload
    })
  },
})

export default onboardingSlice.reducer

2. Incorrect AsyncStorage Value Parsing

Your checkOnboarding function was checking if the stored value exists (non-null) but not parsing it back to a boolean. If the stored value was "false" (a string), it would still set onboarded to true—which is wrong.

Fix: Parse the Stored JSON

Update your checkOnboarding function to parse the stored value:

const checkOnboarding = async () => {
  try {
    const value = await AsyncStorage.getItem('@onBoarding')
    // Parse the string back to a boolean
    const parsedValue = value ? JSON.parse(value) : false
    setOnboarded(parsedValue)
  } catch (err) {
    console.error('Error checking onboarding status:', err)
  } finally {
    setIsLoading(false)
  }
}

3. InitialRouteName Only Runs Once

The initialRouteName prop is only evaluated when the navigator first mounts. Even if onboarded updates later, the navigator won’t re-render with the new route. You need to wait for the AsyncStorage check to complete before rendering the navigator.

Fix: Add a Loading State

Show a loading screen while checking the onboarding status, then render the navigator with the correct initial route:

function RootStack() {
  const Stack = createNativeStackNavigator<RootStackParamList>()
  const [isLoading, setIsLoading] = React.useState(true)
  const [onboarded, setOnboarded] = React.useState(false)

  const checkOnboarding = async () => {
    try {
      const value = await AsyncStorage.getItem('@onBoarding')
      const parsedValue = value ? JSON.parse(value) : false
      setOnboarded(parsedValue)
    } catch (err) {
      console.error('Error checking onboarding status:', err)
    } finally {
      setIsLoading(false)
    }
  }

  useEffect(() => {
    checkOnboarding()
  }, [])

  // Show loading while we fetch the onboarding status
  if (isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <ActivityIndicator size="large" color={theme.colors.primary} />
      </View>
    )
  }

  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName={onboarded ? 'Login' : 'OnboardingScreen'}
        screenOptions={{ headerShown: false }}
      >
        <Stack.Screen name='Login' component={Login} />
        <Stack.Screen name='OnboardingScreen' component={OnboardingScreen} />
        <Stack.Screen name='Tabs' component={Tabs} />
        <Stack.Screen name='DrawerNav' component={DrawerNav} />
        <Stack.Screen
          name='OtpScreen'
          component={OtpScreen}
          options={{
            title: 'OTP',
            headerShown: true,
            headerStyle: { backgroundColor: theme.colors.whiteSmoke },
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  )
}

4. Clean Up the onSkip Handler

Remove the redundant AsyncStorage.setItem call in your skip button—your thunk now handles this:

onSkip={() => {
  dispatch(setOnboardingAsync(true))
  navigation.replace('Login')
}}

These changes should ensure your app correctly persists the onboarding status and navigates to the right screen on startup.

内容的提问来源于stack exchange,提问作者Mohamed Abdinasir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 21:27:43