在React Redux中设置状态的更好做法

时间:2019-04-10 14:33:31

标签: reactjs redux react-redux

我正在学习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
}

我认为我的工作方式更简洁-如果状态复杂,我可以轻松更改需要更改的内容而无需更改原始状态。

4 个答案:

答案 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
相关问题