Что является лучшей практикой для установки состояния в реагирующем редуксе - PullRequest
4 голосов
/ 10 апреля 2019

Я изучаю Redux.Я новичок, поэтому я не хочу развивать плохую привычку с самого начала, поэтому я пишу это.

Документ, который я читаю, говорит, что в редукторах нам нужно всегда устанавливать состояние, в котором мыизмените его - другими словами, сделайте следующее:

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 ]

6 голосов
/ 10 апреля 2019

С первым фрагментом вы нарушаете принцип чистого редуктора.Это означает, что вместо обновления значения непосредственно в состоянии создайте его новую копию и внесите в него изменения.

Согласно Документ :

Редукторыэто просто чистые функции, которые принимают предыдущее состояние и действие и возвращают следующее состояние. Не забудьте вернуть новые объекты состояния, вместо того, чтобы изменять его предыдущее состояние.

Что вы явно нарушаете, присваивая новое значение state, здесь:

state = {...state, valueOne: payload }


Примечание: Не забудьте const newState = {...state}, создаст только поверхностную копию , поэтому, если у вас есть вложенное состояние, этотакже будет нарушать принцип.

В случае вложенного состояния обновите его следующим образом:

var obj = { car: { model: '', num: '' } };

function update() {
  return {
    ...obj,
    car: {
      ...obj.car,
      model: 'abc'
    }
  }
}

console.log('new obj = ', update());

console.log('old obj = ', obj);
2 голосов
/ 10 апреля 2019

Я думаю, что вы слишком усложняете себя. Вот редуктор, который я использую (в качестве примера):

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;
  }
};

Это не должно быть более сложным, чем это.

1 голос
/ 10 апреля 2019

Всегда сохраняйте состояние неизменным, используйте чистую функцию.И есть проблема производительности для вашего подхода.

Ваш подход неизменен.Но помните, что любое отправленное действие пройдет через все редукторы .Это означает, что даже действие не связано с вашим редуктором, вы все равно создаете его мелкую копию.Это необязательно.Не делай этого

// 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
1 голос
/ 10 апреля 2019

Ваше решение не является неизменным, доку есть.В более сложных случаях я рекомендую вам использовать 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})
...