Я играю с простым приложением React Redux, которое увеличивает счетчик при каждом нажатии кнопки. Я тестирую два разных метода увеличения моего счетчика в Redux Reducer. Оба метода изменяют состояние редуктора, однако один из этих методов не вызывает повторную визуализацию моего счетчика.
Вот редуктор, который приведет к повторному рендерингу страницы:
const reducer = (state = {speed: 0}, action) => {
if (action.type ==='INCREMENT_SPEED'){
state = {...state, speed: state.speed+=1
}
return state
}
и вот код, который работает, но не вызывает повторную отрисовку страницы с правильным значением.
const reducer = (state = {speed: 0}, action) => {
if (action.type ==='INCREMENT_SPEED'){
state.speed++
}
return state
}
Единственная разница - это способ обновления состояния. Я предполагаю, что использование инкрементера ++ фактически изменяет состояние, которое не рассматривается как изменение и, следовательно, не вызывает рендеринг страницы.
Если это помогает, вот часть кода, которая добавляется к DOM:
render() {
return (
<div>
<p>SPEED: {this.props.reduxState.reducer.speed}</p>
</div>
)
}
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Да, вы изменяете исходное состояние вместо того, чтобы возвращать новый объект состояния с увеличенным счетчиком.
Вы могли бы это сделать (в данном случае не имеет особого смысла, но показывает проблему)
const reducer = (state = {speed: 0}, action) => {
if (action.type ==='INCREMENT_SPEED'){
state = {...state} // copy the state to a new object
state.speed++; // increment the new object
return state; // return the new state object
}
Таким образом, это новый объект, поэтому старые объекты состояния остаются неизменными.
Вы правы в своем предположении. Во втором примере вы изменяете состояние, и это не приведет к повторному рендерингу. Вы никогда не должны изменять состояние. Всегда делайте копию состояния и возвращайте новое состояние.
Если вы проверите Redux doc, вы обнаружите, что они предлагают использовать либо Object.assign (), либо Синтаксис распространения объекта, чтобы предотвратить изменение состояния.
Оба решения жизнеспособны.
Кстати, использование операторов switch для редукторов рекомендуется.
Использование Object.assign ()
const reducer = (state = {speed: 0}, action) => {
switch (action.type) {
case 'INCREMENT_SPEED':
return Object.assign({}, state, {
speed: state.speed + 1
})
default:
return state
}
}
Использование синтаксиса распространения объекта
const reducer = (state = {speed: 0}, action) => {
switch (action.type) {
case 'INCREMENT_SPEED':
return {...state, speed: state.speed + 1}
default:
return state
}
}
Вы должны вернуть новый объект вместо измененного старого, чтобы запустить повторную визуализацию.