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

React Native Expo项目Redux Persist在Android端重启后无法加载状态

Expo + redux-persist Android端重启后无法加载持久化状态问题

问题现象

用Expo创建项目并集成redux-persist做状态持久化后,出现以下差异:

  • iOS端状态加载完全正常
  • Android端仅在代码热重载时能正常读取存储的状态;App重启后无法获取持久化数据,仅能拿到初始状态

相关代码

store.js

import {combineReducers, configureStore} from '@reduxjs/toolkit'
import {setFirstname, userSlice} from "./user/userSlice";
import AsyncStorage from '@react-native-async-storage/async-storage';
import { persistStore, persistReducer } from 'redux-persist'
import {FLUSH, PAUSE, PERSIST, PURGE, REGISTER, REHYDRATE} from "redux-persist/es/constants";

const persistConfig = {
    key: 'root',
    storage: AsyncStorage,
}

const persistedReducer = persistReducer(persistConfig, userSlice.reducer)

export const store = configureStore({
    reducer: persistedReducer,
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware({
            serializableCheck: {
                ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
            },
        }),
})

export const persistor = persistStore(store)

export default store

app.js

import { StatusBar } from 'expo-status-bar';
import { StyleSheet } from 'react-native';
import React, {useEffect, useState} from 'react';
import BottomNav from "./app/navigations/BottomNav";
import 'react-native-gesture-handler'
import StackNav from "./app/navigations/StackNav";
import {NavigationContainer} from "@react-navigation/native";
import {navigationRef} from "./app/navigations/RootNavigation";
import {Provider} from "react-redux";
import {persistor, store} from "./app/store/store";
import {PersistGate} from "redux-persist/integration/react";
import SpinningLogo from "./app/ui/SpinningLogo";

export default function App() {
    const [isAuth, setAuth] = useState(null)

    useEffect(() => {
        console.log(store.getState().userToken)
        if (store.getState().userToken){
            setAuth(true)
        }
    })

    return (
        <Provider store={store}>
            <PersistGate loading={<SpinningLogo/>} persistor={persistor}>
                <NavigationContainer ref={navigationRef}>
                    <StatusBar style="light" />
                    {isAuth ? (
                        <BottomNav/>
                    ): <StackNav />}
                </NavigationContainer>
            </PersistGate>
        </Provider>
    );
}

const styles = StyleSheet.create({
  container: {
    
  },
});

解决方案

1. 修复状态判断时机与Redux用法问题

原代码直接调用store.getState()且useEffect无依赖项,会在PersistGate完成状态恢复前就执行,拿到初始状态。改用useSelector订阅状态变化,确保状态恢复后再更新导航逻辑:

import { StatusBar } from 'expo-status-bar';
import { StyleSheet } from 'react-native';
import React from 'react';
import BottomNav from "./app/navigations/BottomNav";
import 'react-native-gesture-handler'
import StackNav from "./app/navigations/StackNav";
import {NavigationContainer} from "@react-navigation/native";
import {navigationRef} from "./app/navigations/RootNavigation";
import {Provider, useSelector} from "react-redux";
import {persistor, store} from "./app/store/store";
import {PersistGate} from "redux-persist/integration/react";
import SpinningLogo from "./app/ui/SpinningLogo";

// 抽离导航逻辑为子组件,内部使用useSelector订阅状态
const AppContent = () => {
    const userToken = useSelector(state => state.userToken)
    return (
        <>
            <StatusBar style="light" />
            {userToken ? <BottomNav/> : <StackNav />}
        </>
    )
}

export default function App() {
    return (
        <Provider store={store}>
            <PersistGate loading={<SpinningLogo/>} persistor={persistor}>
                <NavigationContainer ref={navigationRef}>
                    <AppContent />
                </NavigationContainer>
            </PersistGate>
        </Provider>
    );
}

const styles = StyleSheet.create({
  container: {
    
  },
});

2. 适配Android存储读取速度

Android端AsyncStorage读取速度慢于iOS,可在persistConfig中延长状态恢复超时时间:

const persistConfig = {
    key: 'root',
    storage: AsyncStorage,
    timeout: 10000 // 延长至10秒,确保Android有足够时间读取存储
}

3. 确保状态可序列化

redux-persist依赖JSON序列化存储状态,Android对序列化兼容性要求更严格,检查userSlice中的状态是否包含不可序列化类型(如函数、Symbol、未转字符串的Date对象),示例如下:

// userSlice.js 确保状态全为可序列化类型
import { createSlice } from '@reduxjs/toolkit'

const initialState = {
  userToken: null,
  firstname: '',
  // 避免使用函数、原始Date对象等,日期建议转成ISO字符串存储
}

export const userSlice = createSlice({
  name: 'user',
  initialState,
  reducers: {
    setFirstname: (state, action) => {
      state.firstname = action.payload
    },
    // 其他reducer逻辑
  },
})

内容的提问来源于stack exchange,提问作者Moemen Hussein

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 23:50:34