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

React-Redux的dispatch与useSelector在iOS16/Android13设备上失效

Redux Persist 在新设备上的状态更新异常问题

问题现象

用户输入的值可保存到本地存储,常规设备上能通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:23:25