#javascript #reactjs #redux #immutability
#javascript #reactjs #redux #неизменность
Вопрос:
В порядке ли этот редуктор:
function someReducer(state = initialState, action) {
if (action.type === SOME_ACTION) {
const newState = Object.assign( {}, state );
// ...
// doing whatever I want with newState
// ...
return newState;
}
return state;
}
и если в порядке, зачем нам нужны все эти неизменяемые библиотеки, чтобы усложнять нашу жизнь.
p.s Просто пытаюсь понять Redux и неизменность
Комментарии:
1. К какой части у вас есть вопрос? SO не для обзоров кода
2. @ristepan Я бы посоветовал попросить его отреагировать на reddit . Вы можете не обратить на это внимания, хотя здесь это действительно хороший вопрос. ТАК что есть много правил.. Лучше пойти и попросить более гибкие места, как я упоминал.
3. Для глубокого клонирования нам нужно использовать другие альтернативы, потому что
Object.assign()
копирует значения свойств. Если исходное значение является ссылкой на объект, оно копирует только это ссылочное значение.4. Вопрос @JuanMendes ясен.
5.
assign
это не глубокий клон, поэтому вы все равно можете войти и напрямую изменить состояние.
Ответ №1:
export default function (state = initialState, action) {
const actions = {
SOME_ACTION: () => {
return {
...state
}
},
ANOTHER_ACTION: () => {
return {
...state
error: action.error
}
},
DEFAULT: () => state;
}
return actions[action.type] ? actions[action.type]() : actions.DEFAULT();
}
Я предпочитаю делать это вместо этого. Я не большой поклонник инструкций switch.
Комментарии:
1. Впервые вижу этот поток. Вкусно!
2. Проверьте это: medium.com/chrisburgin /… . Он содержит больше примеров и пояснений.
3. Приятно! Спасибо, чувак.
4. Мне это нравится, и я попробую
5. @NicolaeMaties Нет, он возвращает функцию,
actions
константа определена внутри редуктора и содержит сами функции редуктора, которые работают над замыканиями, и предпочтение объектов операторам переключения очень субъективно.
Ответ №2:
Стандартный подход заключается в использовании синтаксиса switch/case
with spread ( ...
) в вашем редукторе.
export default function (state = initialState, action) {
switch (action.type) {
case constants.SOME_ACTION:
return {
...state,
newProperty: action.newProperty
};
case constants.ERROR_ACTION:
return {
...state,
error: action.error
};
case constants.MORE_DEEP_ACTION:
return {
...state,
users: {
...state.users,
user1: action.users.user1
}
};
default:
return {
...state
}
}
}
Затем вы можете использовать синтаксис распространения ES6, чтобы вернуть свое старое состояние с любыми новыми свойствами, которые вы хотите изменить / добавить к нему.
Вы можете прочитать больше об этом подходе здесь …https://redux.js.org/recipes/using-object-spread-operator
Комментарии:
1. Отметим, что
...
это также мелкий клон, и его может быть недостаточно.2. Я думаю, это примерно тот же подход, я понимаю, что теперь назначение не является полной глубокой копией.
3. Да, я также добавил обновление вложенного свойства к своему ответу, чтобы вы могли увидеть пример того, как обновить вложенное свойство.
Ответ №3:
Я нашел то, что мне действительно нравится:
import createReducer from 'redux-starter-kit';
const someReducer = createReducer( initialState, {
SOME_ACTION: (state) => { /* doing whatever I want with this local State */ },
SOME_ANOTHER_ACTION: (state) => { /* doing whatever I want with local State */ },
THIRD_ACTION: (state, action) => { ... },
});
Ответ №4:
Если в вашем состоянии есть вложенные объекты или массивы, Object.assign
или ...
скопирует ссылки на вашу более старую переменную состояния, и это может вызвать некоторую проблему. Это причина, по которой некоторые разработчики используют неизменяемые библиотеки, поскольку в большинстве случаев состояние имеет глубоко вложенный массив или объекты.
function someReducer(state = initialState, action) {
if (action.type === SOME_ACTION) {
const newState = Object.assign( {}, state );
// newState can still have references to your older state values if they are array or orobjects
return newState;
}
return state;
}
Комментарии:
1. Вы только что скопировали его вопрос, здесь нет ответа.
2. @rrd Я думаю, что встроенный комментарий предназначен для ответа.
3. Ответы должны быть очевидными и видимыми без hscrolling.
4. Теперь я также объяснил причину.
5. В конце концов, я думаю, что что-то вроде функции deepassig выполнит эту работу, по крайней мере, для меня. Мне нравится библиотека immer