我正在学习Redux。我是新来的,所以我不想在一开始就养成不良习惯,这就是为什么我要写这个。
我正在阅读的文档说,在reducer中,我们需要始终设置更改状态-换句话说,请执行以下操作:
const someReducer = (state=initState, {type, payload}) => {
switch(type) {
case 'CHANGE_VALUE_ONE' : {
state = {...state, valueOne: payload }
break
}
case 'CHANGE_VALUE_TWO' : {
state = {...state, valueTwo: payload }
break
}
default:
state = state
}
return state
}
我的方法是创建一个newState常量,该常量与我们收到的状态相同,对虚拟对象进行更改并返回它-或在代码中:
const userReducer = (state= {name: null, age: null}, {type, payload}) => {
const newState = {...state}
switch(type) {
case 'CHANGE_VALUE_ONE' : {
newState.valueOne= payload
break
}
case 'CHANGE_VALUE_TWO' : {
newState.valueTwo= payload
break
}
}
return newState
}
我认为我的工作方式更简洁-如果状态复杂,我可以轻松更改需要更改的内容而无需更改原始状态。
答案 0 :(得分:6)
第一个代码段违反了纯减速器的原理。这意味着,与其直接在状态中更新值,不如创建它的新副本并进行更改。
根据Doc:
Reducer只是纯函数,它具有先前的状态和 动作,然后返回下一个状态。 记住要返回新状态 对象,而不是改变以前的状态。
您显然通过向state
分配新值来违反,这是:
state = {...state, valueOne: payload }
注意:不要忘记const newState = {...state}
,只会创建shallow copy,因此,如果您具有嵌套状态,这也会违反该原理。
在嵌套状态下,以这种方式更新它:
var obj = { car: { model: '', num: '' } };
function update() {
return {
...obj,
car: {
...obj.car,
model: 'abc'
}
}
}
console.log('new obj = ', update());
console.log('old obj = ', obj);
答案 1 :(得分:2)
我认为您过于复杂。这是我使用的减速器(作为示例):
import * as types from '../actions/types';
import { Enums } from '../helpers/enums';
const initialState = {
testState: Enums.command.STOP
};
export default function(state = initialState, action) {
switch (action.type) {
case types.SET_CREEP_TEST_STATE:
return {...state, testState: action.testState};
case types.SET_CREEP_TEST_TIME:
return {...state, testime: action.testime};
default: return state;
}
};
它应该没有比这更复杂的了。
答案 2 :(得分:1)
您的解决方案不是一成不变的,建议使用doc。在更复杂的情况下,我建议您使用immer,lib方法类似于您的方法,但是您将突变状态的副本,然后immer
将此副本与状态数据合并以创建新的州。非常适合嵌套数据更改和不变性。您的案例示例:
const userReducer = produce(state, draft => {
switch(type) {
case 'CHANGE_VALUE_ONE' : {
draft.valueOne= payload
break
}
case 'CHANGE_VALUE_TWO' : {
draft.valueTwo= payload
break
}
}
},{name: null, age: null})
答案 3 :(得分:1)
始终保持状态不变,使用纯函数。而且您的方法存在性能问题。
您的方法是一成不变的。但是请记住,任何分派的动作都将通过所有减速器。这意味着即使该动作与您的reducer无关,您仍将为其创建一个新的浅表副本。这不是必需的。不要这样做
// This newState will be created by every action
const newState = {...state}
switch(type) {
case 'CHANGE_VALUE_ONE' : {
newState.valueOne= payload
break
}
case 'CHANGE_VALUE_TWO' : {
newState.valueTwo= payload
break
}
}
return newState