React Redux, я здесь меняю состояние?

Я играю с простым приложением 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>
    )
  }
}

Вы должны вернуть новый объект вместо измененного старого, чтобы запустить повторную визуализацию.

Nonemoticoner 05.11.2018 23:16
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
1
2 105
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Да, вы изменяете исходное состояние вместо того, чтобы возвращать новый объект состояния с увеличенным счетчиком.

Вы могли бы это сделать (в данном случае не имеет особого смысла, но показывает проблему)

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

Другие вопросы по теме