Дочерний компонент не перерисовывается, но родительский компонент перерисовывается. Как заставить рендеринг дочернего компонента? - PullRequest
1 голос
/ 17 октября 2019

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

Я получаю обновленные данные из хранилища избыточности в родительском компоненте, но не в дочерних компонентах. Дочерние компоненты получают данные из хранилища приращений только при первом отображении

Мой родительский компонент Home.js

Объект seaFCLJSON выглядит следующим образом const seaFCLJSON ={"rates": {"sort":"faster", "someOther": "someOtherValues"}};

при добавленииМагазин обновляется, seaFCLJSON выглядит следующим образом const seaFCLJSON ={"rates": {"sort":"cheaper","someOther": "someOtherValues"}};

class Home extends Component {
state = {
    seaFCLJSON: {}
  };

componentDidMount = () => {
     this.setState({ seaFCLJSON: this.props.seaFCLJSON });
  };

 componentWillReceiveProps = nextProps => {
    if (this.state.seaFCLJSON !== nextProps.seaFCLJSON) {
      this.setState({ seaFCLJSON: nextProps.seaFCLJSON });
    }
  };

 render() {
    const { seaFCLJSON } = this.props;
 return (
       <>
    {!isEmpty(seaFCLJSON) && seaFCLJSON.rates && seaFCLJSON.rates.fcl ? (
          <FCLContainer fclJSON={seaFCLJSON} />
        ) : null} //it never rerenders upon getting updated data from redux store

    <h5>{JSON.stringify(seaFCLJSON.rates && seaFCLJSON.rates.sort)}</h5> //it rerenders everytime upon getting updated data from redux store
       </>
     );
  }
}

const mapStateToProps = state => {
  return {
    seaFCLJSON: state.route.seaFCLJSON
  };
};

export default connect(
  mapStateToProps,
  actions
)(Home);

isEmpty.js

export const isEmpty = obj => {
  return Object.entries(obj).length === 0 && obj.constructor === Object;
};

Мой дочерний компонент FCLContainer.js

class FCLContainer extends Component {
  state = {
    seaFCLJSON: {}
  };
  componentDidMount = () => {
    this.setState({ seaFCLJSON: this.props.seaFCLJSON });
  };

  componentWillReceiveProps = nextProps => {
    console.log("outside state value: ", this.state.seaFCLJSON);
    if (this.state.seaFCLJSON !== nextProps.seaFCLJSON) {
      this.setState({ seaFCLJSON: nextProps.seaFCLJSON });
      console.log("inside state value: ", this.state.seaFCLJSON);
    }
  };


  render() {
    const { seaFCLJSON } = this.state;
    console.log("rendering .. parent props: ", this.props.fclJSON);
    console.log("rendering .. redux store props: ", this.props.seaFCLJSON);

    return (
      <>
        <div className="home-result-container">
          <div>
          <h5>This child component never rerenders :(</h5>
          </div>
        </div>
      </>
    );
  }
}

const mapStateToProps = state => {
  return {
    seaFCLJSON: state.route.seaFCLJSON
  };
};

export default connect(
  mapStateToProps,
  actions
)(FCLContainer);

Не знаюНе знаю, есть ли проблемы в родительском компоненте или проблемы в дочернем компоненте. componentWillReceiveProps вызывается в родительском компоненте, но не в дочернем компоненте. Пожалуйста, игнорируйте любые пропущенные точки с запятой или фигурные скобки, потому что я опустил некоторые ненужные коды. Изменить 1: Я просто продублировал значение из реквизита в состояние только для целей отладки.

Буду признателен за вашу помощь. Спасибо.

Редактировать 2 : Я непосредственно изменял объект в действиях с избыточностью. Вот почему CWRP не уволили. Это была проблема. Для получения дополнительной информации проверьте мой ответ ниже.

Ответы [ 4 ]

0 голосов
/ 27 октября 2019

Я обнаружил проблему, я непосредственно мутировал объект в действиях. Я только знал, что state не должен быть напрямую мутирован в class или внутри reducer. Я изменил действия, в которых я непосредственно изменял объект, а затем сохранял его в хранилище резервов через dispatch, а затем я получил обновленный реквизит в CWRP. Это действительно заняло у меня много раз, чтобы понять. Такую проблему трудно выяснить, по крайней мере, для меня. Я думаю, я получил это от https://github.com/uberVU/react-guide/issues/17

Урок, который я усвоил: Никогда не мутировал объект напрямую

Я изменил это

//FCL sort by faster
export const sortByFasterFCLJSON = () => async (dispatch, getState) => {
  let seaFCLJSON = getState().route.seaFCLJSON;
  if (!seaFCLJSON.rates) return;
  seaFCLJSON.rates.fcl = _.orderBy(
    seaFCLJSON.rates.fcl,
    ["transit_time"],
    ["asc"]
  );

  seaFCLJSON.rates.sort = "Faster"; //this is the main culprit

  dispatch({ type: SET_SEA_FCL_JSON, payload: seaFCLJSON });
};

к этому

//FCL sort by faster
export const sortByFasterFCLJSON = () => async (dispatch, getState) => {
  let seaFCLJSON = getState().route.seaFCLJSON;
  if (!seaFCLJSON.rates) return;
  seaFCLJSON.rates.fcl = _.orderBy(
    seaFCLJSON.rates.fcl,
    ["transit_time"],
    ["asc"]
  );

  // seaFCLJSON.rates.sort = "Faster"; //this was the main culprit, got lost

  seaFCLJSON = {
    ...seaFCLJSON,
    rates: { ...seaFCLJSON.rates, sort: "Faster" }
  };

  dispatch({ type: SET_SEA_FCL_JSON, payload: seaFCLJSON });
};

сила не мутирующих данных

Примечание: Устранение неполадок Redux

0 голосов
/ 17 октября 2019

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

О вашей проблеме - скорее всего, это условие не соответствует, поэтому дочерний компонент не запускает

!isEmpty(seaFCLJSON) && seaFCLJSON.rates && seaFCLJSON.rates.fcl

проверить его в отладчике

0 голосов
/ 17 октября 2019

Насколько я понимаю, ваша проблема в том, что вы передаете следующее своему дочернему компоненту:

<FCLContainer fclJSON={seaFCLJSON} />

Но вы предполагаете, что получили реквизит с именем 'seaFCLJSON':

 componentDidMount = () => {
this.setState({ seaFCLJSON: this.props.seaFCLJSON });

};

Вы должны изменить свой код на:

<FCLContainer seaFCLJSON={seaFCLJSON} />

Кроме того, как уже упоминал @Paul McLoughlin, вы должны использовать опору напрямую, а не добавлять ее вваше состояние.

0 голосов
/ 17 октября 2019

componentWillReceiveProps устареет в реакции 17, вместо этого используйте componentDidUpdate, который вызывается сразу после обновления Попробуйте что-то вроде этого:

componentDidUpdate(prevProps, prevState) {
    if (this.prevProps.seaFCLJSON !== this.props.seaFCLJSON) {
      this.setState({ seaFCLJSON: this.props.seaFCLJSON });
    }
  };
...