Компонент не перерисовывает при изменении состояния - Redux - PullRequest
0 голосов
/ 02 мая 2018

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

компонент (Домен)

...
<Add
   onClick={() => {
   domain.routes.push({
     from: 'foo',
     to: 'bar'
   });
   this.props.setDomain(this.props.domainIndex, domain);
}} />
...

редуктор

case 'SET_DOMAIN':
  let tmpState = {...state}
  tmpState.domains[action.index] = action.value;
  return {...tmpState}

действие

export const setDomain = (index, domain) => ({
  type: 'SET_DOMAIN',
  value: domain,
  index: index
});

контейнер

import { connect } from 'react-redux';
import { setDomain, setRoute } from '../actions';
import Domain from '../components/pages/domain';

const mapStateToProps = state => ({
  domains: state.domains
});

const mapDispatchToProps = dispatch => ({
  setDomain: (index, domain) => dispatch(setDomain(index, domain)),
  setRoute: (domainIndex, routeIndex, route) =>
    dispatch(setRoute(domainIndex, routeIndex, route))
});

export default connect(mapStateToProps, mapDispatchToProps)(Domain);

Из расширения redux chrome я вижу, что setDomain вызывается и состояние возвращается правильно:

enter image description here

1 Ответ

0 голосов
/ 02 мая 2018

React Redux пытается улучшить производительность, делая поверхностное равенство проверка ссылок на входящие реквизиты в shouldComponentUpdate, и если все ссылки одинаковы, shouldComponentUpdate возвращает false пропустить фактическое обновление исходного компонента.

Важно помнить, что всякий раз, когда вы обновляете вложенное значение, Вы также должны вернуть новые копии чего-либо выше в вашем штате дерево. Если у вас есть state.a.b.c.d, и вы хотите обновить d, вам также нужно будет вернуть новые копии c, b, a и state.

С https://redux.js.org/faq/react-redux#react-not-rerendering

{...object} - это всего лишь мелкий клон. Дочерний объект объекта будет по-прежнему иметь ту же ссылку. Поэтому для Redux дочерний объект не обновляется.

Я думаю, что самый быстрый способ решить эту проблему - использовать Lodash cloneDeep .

let tmpState = _.cloneDeep(state);

или

tmpState.domains = _.cloneDeep(tmpState.domains);

Но это идет с затратами на производительность.

Кроме того, вы можете отменить клонирование пострадавшего ребенка 1 на 1.

...