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

react-native-encrypted-storage结合redux-persist时状态未更新问题

Redux状态无法更新问题排查(redux-persist + react-native-encrypted-storage)

尝试用react-native-encrypted-storage配合redux-persist实现安全持久化存储,但调用setPersistedDataaction后,日志能打印但组件状态未更新。相关代码如下:

store.ts

import {combineReducers, configureStore} from '@reduxjs/toolkit';
import persistedReducer from './persistedSlice';
import {
  FLUSH,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
  REHYDRATE,
  persistReducer,
  persistStore,
} from 'redux-persist';
import EncryptedStorage from 'react-native-encrypted-storage';
import {TypedUseSelectorHook, useDispatch, useSelector} from 'react-redux';

const combinedReducer = combineReducers({
  persisted: persistedReducer,
});

const persistedCombinedReducer = persistReducer(
  {
    key: 'root',
    storage: EncryptedStorage,
    whitelist: ['persisted'],
  },
  combinedReducer,
);

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

  const persistedStore = persistStore(store);

  return {store, persistedStore};
};

const {store, persistedStore} = createStores();

export {store, persistedStore};

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

type DispatchFunc = () => AppDispatch;
export const useAppDispatch: DispatchFunc = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

persistedSlice.ts

import {PayloadAction, createSlice} from '@reduxjs/toolkit';

interface PersistedState {
  user?: {
    id: string;
    name: string;
  };
  token?: string;
}

const initialState: PersistedState = {};

const persistedSlice = createSlice({
  name: 'persisted',
  initialState,
  reducers: {
    setPersistedData(state, action: PayloadAction<PersistedState>) {
      console.log('AAAA: ', {
        state,
        data: action.payload,
      });
      state = action.payload;
    },
  },
});

export const {setPersistedData} = persistedSlice.actions;

export default persistedSlice.reducer;

组件代码

import React from 'react';
import {useAppDispatch, useAppSelector} from './store';
import {Button, Text, View} from 'react-native';
import {setPersistedData} from './persistedSlice';

const Consumer = () => {
  const user = useAppSelector(state => state.persisted.user);
  const dispatch = useAppDispatch();

  return (
    <View>
      <Text>User info: {user ? JSON.stringify(user) : 'unknown'}</Text>
      <Button
        title="Set user"
        onPress={() => {
          dispatch(
            setPersistedData({
              user: {
                id: '1',
                name: 'Mister A',
              },
              token: 'abcA@@',
            }),
          );
        }}
      />
    </View>
  );
};

export default Consumer;

问题原因

在persistedSlice.ts的setPersistedDatareducer中,直接执行state = action.payload是无效的。Redux Toolkit的createSlice使用Immer库处理不可变状态,直接给state变量赋值只会改变局部变量的引用,不会修改Immer包装的原始状态对象,因此Redux无法检测到状态变化。

修复方案

修改setPersistedData的实现,有两种可行方式:

方式一:返回新的状态对象

直接返回action.payload,Immer会自动处理状态替换:

setPersistedData(_state, action: PayloadAction<PersistedState>) {
  console.log('AAAA: ', {
    data: action.payload,
  });
  return action.payload;
}

方式二:使用Immer的可变语法更新状态

通过Object.assign或者逐个属性赋值来修改原state对象:

setPersistedData(state, action: PayloadAction<PersistedState>) {
  console.log('AAAA: ', {
    state,
    data: action.payload,
  });
  // 用Object.assign合并新数据到原状态
  Object.assign(state, action.payload);
  
  // 或者逐个属性赋值(适合部分更新场景)
  // state.user = action.payload.user;
  // state.token = action.payload.token;
}

选择其中一种方式修改后,Redux就能正确检测到状态变化,组件会重新渲染并展示更新后的user信息。

内容的提问来源于stack exchange,提问作者Dao Danh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:05:42