【发布时间】:2017-06-30 16:26:17
【问题描述】:
tldr;版本:调用 setState 后父级未重新渲染...
我有一个显示多个组件的仪表板视图。加载数据的子组件工作得很好。但是我有仪表板的另一部分,我计划使用相同的数据集加载同一组件的多个版本。因此,我不是对同一个数据集进行 6 次 api 调用,而是通过父级提取数据并将其发送给子级。我还使用路由参数来指示要查找的公司。
包含自己的 api 调用的组件运行良好,与路由参数一起运行良好。这是我在出现问题的父级中进行 api 调用的组件。父级正在渲染,然后是子级,然后 api 调用完成并设置状态,但没有重新加载。所以随着路由参数的变化,组件会显示上一次点击的数据(本质上总是落后一个)。
我尝试更改将其绑定到的响应事件,我使用了映射函数,确保“this”是我想要的“this”(它是)......没有骰子。我知道它正在正确更新状态,如果我 forceUpdate() 正确的数据显示在组件中(但我不能这样做,它将迫使我将 forceUpdate() 添加到反应更新方法中,这将导致它不断重新加载)。
有什么想法吗??这是一些精简/混淆的代码:
家长
...
class ClientDash extends Component {
constructor(props) {
super(props);
this.state = { chartOptions: {}, data1: {}, data2: {}, data3: {}, data4: {}, data5: {}, data6: {}, loaded: false };
}
loadData(clientID) {
var currYear = moment().year();
var chartData = {
labels: [(currYear-4).toString(), (currYear-3).toString(), (currYear-2).toString(), (currYear-1).toString(), currYear.toString()],
datasets: [{
type: 'bar',
label: 'Cat1',
backgroundColor: this.props.colors[0].borderColor,
borderColor: 'white',
borderWidth: 3,
data: [null, null, null, null, null]
}, {
type: 'bar',
label: 'Cat2',
backgroundColor: this.props.colors[1].borderColor,
borderColor: 'white',
borderWidth: 3,
data: [null, null, null, null, null]
}, {
type: 'bar',
label: 'Cat3',
backgroundColor: this.props.colors[2].borderColor,
borderColor: 'white',
borderWidth: 3,
data: [null, null, null, null, null]
}, {
type: 'bar',
label: 'Cat4',
backgroundColor: this.props.colors[3].borderColor,
borderColor: 'white',
borderWidth: 3,
data: [null, null, null, null, null]
}]
};
var chartOptions = {
tooltips: {
mode: 'index',
intersect: true
},
responsive: true
};
axios(apiCall)
.then(d => {
var data = d.data;
var data1 = _.clone(chartData),
data2 = _.clone(chartData),
data3 = _.clone(chartData),
data4 = _.clone(chartData),
data5 = _.clone(chartData),
data6 = _.clone(chartData);
/* some data manipulation */
console.log('loading data');
console.log(this);
this.setState({ chartOptions: chartOptions, data1: data1, data2: data2, data3: data3, data4: data4, data5: data5, data6: data6, loaded: true });
// this.forceUpdate();
}).then()
.catch(function (error) {
console.log(error);
})
}
componentWillUpdate(nextProps) {
this.initComp(nextProps.params.clientID);
}
shouldComponentUpdate(nextProps) {
return nextProps.params.clientID != this.props.params.clientID;
}
componentWillMount() {
this.initComp(this.props.params.clientID);
}
render() {
console.log('parent rendering')
// removed all unnecessary code below
return (
<div className="wrapper wrapper-content animated fadeIn">
<div className="row">
<div className="col-lg-4">
<div className="ibox">
<div className="ibox-content">
<MetricsColumnChart metricsData={this.state.data1} options={this.state.chartOptions} />
</div>
</div>
</div>
</div>
</div>
)
}
}
/**
* Map the state to props.
*/
const mapStateToProps = (state) => ({
...state
});
/**
* Map the actions to props.
*/
const mapDispatchToProps = (dispatch) => {
return bindActionCreators(Actions, dispatch)
};
/**
* Connect the component to
* the Redux store.
*/
export default connect(
mapStateToProps,
mapDispatchToProps
)(ClientDash)
儿童
import React, { Component } from 'react';
import {Bar} from 'react-chartjs-2';
var _ = require('lodash');
class MetricsColumnChart extends Component {
render() {
console.log('child rendering')
return(
<Bar data={this.props.metricsData} options={this.props.options} />
)
}
}
export default MetricsColumnChart
【问题讨论】:
-
如果父母不更新,孩子也不会。您必须相应地更新您的
shouldComponentUpdate(它接受第二个参数nextState) -
@TylerSebastian 是对的。如果您通过控制台登录
shouldComponentUpdate,它应该会出现。它已经停在那里了。 -
感谢您的帮助,您说的都是对的。我刚刚在
shouldComponentUpdate方法的返回值中添加了一个!(_.isEqual(nextState, this.state))