tldr; version:父类在setState调用后不重新渲染...
我有一个渲染多个组件的仪表板视图。加载数据的子组件工作得很好。但我有仪表板的另一部分,我计划使用相同的数据集加载同一组件的多个版本。因此,我不是对同一个数据集进行6次api调用,而是通过父级将数据拉入并将其发送给子级。此外,我正在使用路由参数来指示要查找的公司。
包含自己的api调用的组件运行良好,与路径参数一起正常运行。它是我在我遇到问题的父母中进行api调用的组件。父进行渲染,然后是子进程,然后api调用结束并设置状态,但不重新加载。因此,当路径参数发生变化时,组件会显示前一次点击的数据(基本上总是落在后面)。
我已经尝试更改哪些反应事件与之相关联,我已经使用了映射功能,确保"这个"是"这"我想要的(它是)......没有骰子。我知道它正确更新状态,如果我在forceUpdate()中显示正确的数据(但是我不能这样做,那么它会强制我将forceUpdate()添加到react更新方法中会使它不断重新加载。)
任何想法?这是一些精简/混淆的代码:
父
...
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
答案 0 :(得分:5)
问题在于你的shouldComponentUpdate
。现在,只有当新clientID
的道具与当前clientID
不同时,它才会返回true。因此,当您在API调用结束时运行this.setState()
时,组件不会更新,因为您没有收到新的道具。
基本上,
有两种方法可以解决这个问题:
shouldComponentUpdate
,以便React决定组件何时更新(运行this.setState
或接收新更新时)shouldComponentUpdate
nextState
添加第二个参数,并比较旧状态和新状态,以确定组件何时更新。顺便说一句,我发现您在componentWillMount
进行了API调用。 There are some good reasons why you should use componentDidMount
isntead.