React与Redux:如何修复用于存储登录用户临时变量的action和reducer
修复方案
核心问题
- 类型不匹配:reducer中判断的是经过
REQUEST/SUCCESS包装的action类型,但你当前定义的action返回的是原始ACTION_TYPES类型,两者完全不匹配,不会触发任何更新逻辑 - 无状态更新逻辑:所有reducer分支都仅返回原状态副本,没有处理action携带的payload来更新数据
- 缺少更新操作的action:只实现了getData和createData,没有对应PUT操作的updateData
纯前端内存存储修复代码(不需要调用后端接口,仅存全局redux状态)
符合你不需要写入数据库、仅存全局可用变量的需求:
// 纯前端同步存储不需要用到异步状态包装,无需引入REQUEST/SUCCESS/FAILURE import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util'; export const ACTION_TYPES = { FETCH_DATA : 'personInfo/FETCH_DATA', CREATE_DATA : 'personInfo/CREATE_DATA', UPDATE_DATA : 'personInfo/UPDATE_DATA' }; export interface PersonInfo { info: { role?: string | number, environment ?: string | number } } // 初始化状态 const initialState: PersonInfo = { info: { role: '', environment : '' } } // 修复后的reducer export default (state: PersonInfo = initialState, action): PersonInfo => { switch(action.type) { // 读取操作不需要修改状态,直接返回 case ACTION_TYPES.FETCH_DATA: return { ...state }; // 新增和修改逻辑一致,都是覆盖info字段 case ACTION_TYPES.CREATE_DATA: case ACTION_TYPES.UPDATE_DATA: return { ...state, info: { ...state.info, ...action.payload } }; default: return state; } } // 读取数据action,不需要传参,数据直接从redux state读取 export const getData = () => { return { type: ACTION_TYPES.FETCH_DATA } } // 新增数据action,对应首次提交的POST操作 export const createData = (entity: {role: string | number, environment: string | number}) => { const userInfo = { role: entity.role, environment: entity.environment } return { type: ACTION_TYPES.CREATE_DATA, payload: userInfo }; }; // 新增更新数据action,对应修改操作的PUT操作 export const updateData = (entity: Partial<{role: string | number, environment: string | number}>) => { return { type: ACTION_TYPES.UPDATE_DATA, payload: entity }; };
组件使用示例
import { useDispatch, useSelector } from 'react-redux'; import { createData, updateData, PersonInfo } from './你的reducer文件路径'; const UserForm = () => { const dispatch = useDispatch(); // 读取全局存储的用户信息 const personInfo = useSelector((state: any) => state.personInfo as PersonInfo); // 首次提交表单触发 const handleFirstSubmit = (formValues) => { dispatch(createData(formValues)); }; // 修改已保存信息触发 const handleModify = (newValues) => { // 支持只传单个要修改的字段,比如只传{role: 'admin'} dispatch(updateData(newValues)); }; return <div> 预填充角色:{personInfo.info.role} 预填充环境:{personInfo.info.environment} </div> }
优化建议(刷新页面数据不丢失)
如果需要刷新页面后保存的信息仍然存在,可以在更新状态时同步写入localStorage:
// 初始化时从localStorage读取 const initialState: PersonInfo = { info: JSON.parse(localStorage.getItem('personInfo') || '{"role":"","environment":""}') } // reducer更新分支同步存储 case ACTION_TYPES.CREATE_DATA: case ACTION_TYPES.UPDATE_DATA: const newInfo = { ...state.info, ...action.payload }; localStorage.setItem('personInfo', JSON.stringify(newInfo)); return { ...state, info: newInfo };
如果你的流程需要先调用后端接口再更新全局状态,只需要配合redux-thunk/redux-saga处理异步逻辑,在接口请求成功后dispatch对应action即可。
内容的提问来源于stack exchange,提问作者Jack23
相关产品推荐
相关产品推荐

