redux-starter-kit的createSlice中的突变状态

时间:2019-09-02 21:38:23

标签: javascript reactjs redux

我使用createSlice()中的redux-starter-kit。借助immer可以简化化简器中的状态。但是他们说immer中有一些限制。例如,您不应变异并同时从化简器返回新状态。所以我选择像这样变异 第一次尝试

const testSlice = createSlice({
    initialState: 4,
    reducers:{
        increment: state => {state = state + 1},
        decrement: state => {state = state - 1}
    }});

但是此代码不起作用。特别是,当我调度crement()或decrement()时,我在Redux Dev Tools中看到了动作,但是状态保持不变。 好的。让我们像这样返回新状态:
第二次尝试

const testSlice = createSlice({
    initialState: 4,
    reducers:{
        increment: state => state + 1,
        decrement: state => state - 1
    }});

并且此代码按预期工作。 毕竟,我已经尝试过这种构造了
第三次尝试

const testSlice = createSlice({
    initialState: {counter:4},
    reducers:{
        increment: state => {state.counter = state.counter + 1},
        decrement: state => {state.counter = state.counter - 1}
    }});

这也有效 问题是-为什么第三个无效而同时第一个无效?

2 个答案:

答案 0 :(得分:2)

第一个示例不起作用的原因是因为您没有改变状态-您只是将作为变量的变量 state重新分配给化简器。在第三次尝试中,将状态用作对象。该对象将作为参数通过引用传递给您的化简器 ,因此您可以修改其属性。与redux无关,这是Javascript的工作方式。

答案 1 :(得分:0)

仅以示例的方式扩展Damnjan的出色答案,并注意在Javascript中不存在按引用传递ala C ++。 一切都是按价值传递的。

传递基元(字符串,数字,bigint,布尔值,未定义和符号)时,会将指针的副本分配给函数内部的局部变量。但是,当修改该值时,将创建一个新值,因为原语是自然界不可变的,并且本地指针“指向”了这个新的内存地址,而不是原始地址。

let test = { a: 0, b: 'foo', c: false };

function modifyPrimitives(a, b, c)
{
    a = a + 1;
    b = 'foo';
    c = true;
}
modifyPrimitives(test.state);

console.log(test); // { a: 0, b: 'foo', c: false }

传递对象时,会发生同样的情况;该对象的指针的副本已分配给局部变量。您可以修改此对象的嵌套属性,但不能更改原始对象以指向另一个对象。您只有本地指针,您所能做的就是将其“重新指向”到新对象。

let test = { a: 0, b: 'foo', c: false };

function modifyObject(obj)
{
    obj.a = obj.a + 1;
    obj.b = 'foo';
    obj.c = true;
    
    obj = { wow: 'omgwtfbbq' }; // this won't change the object outside
}
modifyObject(test);

console.log(test); // {a: 1, b: "foo", c: true}