React-Redux的dispatch与useSelector在iOS16/Android13设备上失效
问题现象
用户输入的值可保存到本地存储,常规设备上能通过console.log确认action已分发,且useSelector能正常读取值。但在iPhone 14(iOS 16.x)及部分Android 13新版本设备上出现异常:既无法触发reducer中的console.log,也无法通过useSelector读取更新后的值。修改store配置中的key和storage参数后问题仍未解决,怀疑问题出在store配置上。
包版本
"react": "17.0.2", "react-native": "0.66.4", "@reduxjs/toolkit": "^1.8.2", "react-redux": "^7.2.6", "redux": "^4.1.2", "redux-persist": "^6.0.0",
Store 配置文件
import {configureStore} from '@reduxjs/toolkit'; import rootReducer from './reducers'; import { persistStore, persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER, } from 'redux-persist'; import AsyncStorage from '@react-native-async-storage/async-storage'; import {name as appName} from '../../app.json'; const persistConfig = { key: 'root', // 尝试改为primary无效 whitelist: ['userReducer'], keyPrefix: appName, storage: AsyncStorage, // 尝试更换其他storage无效 }; const persistedReducer = persistReducer(persistConfig, rootReducer); export default () => { const store = configureStore({ reducer: persistedReducer, middleware: getDefaultMiddleware => getDefaultMiddleware({ immutableCheck: false, serializableCheck: { ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], }, }), }); let persistor = persistStore(store, [{manualPersist: true}]); return {store, persistor}; };
Login 组件代码
const {number, chat} = useSelector(store => store.userReducer); const [num, setNum] = useState('') // 以下dispatch在登录函数中调用,登录函数内的console.log可正常执行 dispatch({ type: 'SET_EMPTY_CHAT', }); dispatch({ type: 'SET_NUMBER', payload: num });
UserReducer 代码
import {createReducer} from '@reduxjs/toolkit'; const initialState = { chat: [], number: '' }; export const userReducer = createReducer(initialState, { SET_EMPTY_CHAT: (state, action) => { const {payload} = action; console.log('SET_EMPTY_CHAT called'); state.chat = []; }, SET_NUMBER: (state, action) => { const {payload} = action; console.log('SET_NUMBER called'); state.number = payload; } })
排查与解决方案
1. 修正persistStore的参数格式
你调用persistStore时传入的[{manualPersist: true}]格式错误,persistStore的第二个参数应为回调函数,而非配置数组。正确写法如下:
// 错误写法 let persistor = persistStore(store, [{manualPersist: true}]); // 正确写法 let persistor = persistStore(store); // 若需手动触发持久化,后续在合适时机调用persistor.persist()即可
2. 适配AsyncStorage版本
iOS 16+和Android 13的存储机制有变更,确保@react-native-async-storage/async-storage版本适配RN 0.66.4,建议升级到^1.17.10(RN 0.66.x的稳定兼容版),避免存储读写异常阻塞rehydrate流程。
3. 排除持久化逻辑干扰
临时移除persistReducer,测试纯Redux状态更新是否正常:
export default () => { const store = configureStore({ reducer: rootReducer, middleware: getDefaultMiddleware => getDefaultMiddleware({ immutableCheck: false, serializableCheck: { ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER], }, }), }); return {store}; };
如果纯Redux状态更新正常,说明问题出在持久化流程中。
4. 调试持久化状态
在App入口添加persistor状态监听,查看rehydrate是否完成:
persistor.subscribe(() => { const { bootstrapped } = persistor.getState(); console.log('Persistor bootstrapped:', bootstrapped); });
若bootstrapped始终为false,说明持久化的rehydrate过程未完成,导致后续状态更新被阻塞。
5. 避免存储键名冲突
keyPrefix会与key拼接成最终存储键名,若appName包含特殊字符(空格、中文等),可能在新系统中解析异常。临时移除keyPrefix测试:
const persistConfig = { key: 'root', whitelist: ['userReducer'], // keyPrefix: appName, // 临时注释 storage: AsyncStorage, };
内容的提问来源于stack exchange,提问作者Copy Paste

