繁体   English   中英

子组件不会重新渲染,但父组件会重新渲染。 如何让子组件重新渲染?

[英]Child component doesn't rerender but parent component does rerender. How to make child component rerender?

父组件在收到新道具时会重新渲染,但其子组件不会重新渲染。 子组件仅第一次渲染,从不重新渲染,也不会从 redux 商店接收道具

我正在从 redux 存储在父组件中而不是在子组件中获取更新的数据。 子组件仅在第一次渲染时从 redux 存储接收数据

我的父组件Home.js

Object seaFCLJSON 看起来像这样const seaFCLJSON ={"rates": {"sort":"faster", "someOther": "someOtherValues"}};

当 redux 存储更新时,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);

不知道是Parent组件有问题还是子组件有问题。 componentWillReceiveProps在父组件中被调用,但在子组件中不被调用。 请忽略任何缺少的分号或大括号,因为我省略了一些不必要的代码。 编辑1:我只是出于调试目的将道具中的值复制到 state 。

我会感谢你的帮助。 谢谢你。

编辑 2 :我在 redux 操作中直接更改了 object。 这就是CWRP没有被解雇的原因。 这就是问题所在。 有关更多信息,请查看下面的答案。

componentWillReceiveProps将在 react 17 中被弃用,改用componentDidUpdate ,它在更新发生后立即调用尝试这样的事情:

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

首先从props复制value到state是绝对没有意义的,这是什么意思? 完全没有意义,只是把它放在道具里

关于您的问题-很可能此条件不匹配,这就是子组件不触发的原因

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

在调试器中检查

据我所知,您的问题是您将以下内容传递给您的子组件:

<FCLContainer fclJSON={seaFCLJSON} />

但是您假设您收到了一个名为“seaFCLJSON”的道具:

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

};

您应该将代码更改为:

<FCLContainer seaFCLJSON={seaFCLJSON} />

除此之外,正如@Paul McLoughlin 已经提到的,您应该直接使用该道具,而不是将其添加到您的 state 中。

我发现我在操作中直接改变 object 的问题。 我只知道state不应该在class或内部reducer中直接突变。 我更改了直接更改 object 然后通过dispatch将其保存在 redux 存储中的操作,然后我在 CWRP 中收到了更新的道具。 这真的花了我很多次才弄明白。 这种问题至少对我来说很难找到。 我想我是从https://github.com/uberVU/react-guide/issues/17那里得到的

我学到的一个教训:永远不要直接改变 Object

我改变了这个

//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 故障排除

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM