Reducer中ES6 Class对象状态更新异常问题求助
问题根源
你遇到的核心问题是违反了Redux Reducer的纯函数原则,同时直接修改了原状态实例的引用,导致Redux无法检测到状态变化:
- 你在Reducer里直接修改了
initialState(也就是当前的state实例),而不是创建一个新的状态实例 - 因为你返回的是同一个
UserModel实例引用,Redux对比prevState和nextState时发现引用完全相同,就会认为状态没有更新,所以不会触发组件重渲染
修复方案
Redux要求Reducer必须返回新的状态引用,不能直接修改原状态。针对你的UserModel,可以用以下两种方式修复:
方案1:在Reducer中创建新的UserModel实例
修改userReducer,不要直接修改原state,而是创建一个新的UserModel实例,复制原实例的属性后再更新:
import { USER } from '../constants' import type { IUserInitialState, IUserAction } from '../types' import { UserModel } from '../models' const initialState: IUserInitialState = new UserModel() export const userReducer = (state: IUserInitialState = initialState, action: IUserAction): IUserInitialState => { switch (action.type) { case USER.LOGIN_REQUEST: // 创建新的UserModel实例 const newState = new UserModel() // 复制原state的user属性到新实例(浅拷贝足够的话用展开运算符,深拷贝需用对应方法) newState.userModel = { ...state.user } // 更新新实例的isLogging属性 newState.userIsLogging = action.payload return newState default: return state } }
方案2:给UserModel添加生成新实例的方法
更优雅的方式是在UserModel内部添加一个方法,返回一个更新了指定属性的新实例,这样Reducer逻辑会更简洁:
// UserModel.ts export class UserModel { user: IUserModel = { username: '', password: '', isLogging: false } set userModel(userObject: IUserModel) { this.user = userObject } set userIsLogging(logging: boolean) { this.user.isLogging = logging } get userIsLogging() { return this.user.isLogging } // 添加生成新实例的方法,避免直接修改原实例 withIsLogging(isLogging: boolean): UserModel { const newModel = new UserModel() // 复制当前实例的user属性并更新目标字段 newModel.userModel = { ...this.user, isLogging } return newModel } }
然后在Reducer里调用这个方法:
// userReducer.ts export const userReducer = (state: IUserInitialState = initialState, action: IUserAction): IUserInitialState => { switch (action.type) { case USER.LOGIN_REQUEST: // 调用withIsLogging获取全新实例 return state.withIsLogging(action.payload) default: return state } }
关键知识点回顾
- Redux Reducer必须是纯函数:不能修改传入的
state参数,必须返回新的状态对象/实例 - Redux通过引用对比判断状态是否更新:如果返回的状态和原状态引用相同,Redux会认为状态没有变化,不会触发组件更新
- 对于类实例的状态管理,一定要确保每次更新都返回新的实例,而不是修改原实例
内容的提问来源于stack exchange,提问作者Subrata Banerjee
相关产品推荐
相关产品推荐

