父组件在收到新道具时会重新渲染,但其子组件不会重新渲染。子组件仅是首次渲染,从不重新渲染或从redux存储接收道具
我从Redux存储中获取了更新数据,这些存储在Parent组件中,而不在子组件中。子组件仅在首次渲染时才从redux存储接收数据
我的父级组件Home.js
对象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);
我不知道在上级组件中有问题还是在下级组件中有问题。 componentWillReceiveProps
在父组件中被调用,但在子组件中不被调用。请忽略任何遗漏的分号或花括号,因为我省略了一些不必要的代码。
编辑1:我只是将props的值复制到state只是为了调试。
感谢您的帮助。谢谢。
编辑2 :我直接在redux操作中更改了对象。这就是CWRP没有被解雇的原因。是问题所在。有关更多信息,请在下面查看我的答案。
答案 0 :(得分:0)
componentWillReceiveProps
将在反应17中弃用,请改用componentDidUpdate
,它在更新发生后立即被调用
尝试这样的事情:
componentDidUpdate(prevProps, prevState) {
if (this.prevProps.seaFCLJSON !== this.props.seaFCLJSON) {
this.setState({ seaFCLJSON: this.props.seaFCLJSON });
}
};
答案 1 :(得分:0)
首先,将价值从道具复制到状态绝对是没有意义的,它的含义是什么?完全没有意义,只需将它放在道具中
关于您的问题-最有可能是这种情况不匹配,这就是为什么子组件不会触发
!isEmpty(seaFCLJSON) && seaFCLJSON.rates && seaFCLJSON.rates.fcl
在调试器中检查
答案 2 :(得分:0)
据我所知,您的问题是将以下内容传递给子组件:
<FCLContainer fclJSON={seaFCLJSON} />
但是您假设您收到了一个名为“ seaFCLJSON”的道具:
componentDidMount = () => {
this.setState({ seaFCLJSON: this.props.seaFCLJSON });
};
您应该将代码更改为:
<FCLContainer seaFCLJSON={seaFCLJSON} />
除此之外,正如@Paul McLoughlin已经提到的那样,您应该直接使用道具,而不是将其添加到您的状态。
答案 3 :(得分:0)
我发现我直接在操作中更改对象的问题。我只知道state
不应直接在class
或reducer
内部进行突变。我更改了直接更改对象的操作,然后通过dispatch
将其保存在redux存储中,然后在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 });
};