Reputation: 9273
My question is why the component did not update after update the props. This is my code that explain me well:
export default class App extends React.Component {
constructor(props) {
super(props);
this.topWeakSlotsData = {};
this.topWeakSlotsData['loading'] = true;
this._fetchWeeklyWeakSlots();
}
_fetchWeeklyWeakSlots() {
var _this = this;
fetch("...")
.then(function(response) {
return response.json()
}).then(function(json) {
_this._elaborateTopWeakSlots(json['return']);
}).catch(function(ex) {
console.log('parsing failed', ex)
})
}
_elaborateTopWeakSlots(data) {
...
this.topWeakSlotsData['options'] = {
...
}
this.topWeakSlotsData['loading'] = false;
}
render() {
return (
<HighchartContainer data = {this.topWeakSlotsData} container ="chart1" />
)
}
}
export default class HighchartContainer extends Component {
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps, nextState) {
console.log("should update");
return true;
}
componentWillReceiveProps(nextProps) {
console.log(nextProps);
}
renderLoading() {
return (
<div>
<Loader />
</div>
);
}
renderChart() {
return (
<div>
<Highchart container = {this.props.container} options = {this.props.data.options}/>
</div>
);
}
render() {
return (
<div>
{this.props.data.loading ? this.renderLoading() : this.renderChart()}
</div>
);
}
}
As you can see when the fetch finish I change the loading
from true
to false
and I fill also the options array, but shouldComponentUpdate
or componentWillReceiveProps
is not called and the component is not refreshed, what I wrong?
Upvotes: 0
Views: 190
Reputation: 4039
The App
component will only re-render the HighChartContainer
component when either App's props or state changes. You are currently storing topWeakSlotsData
as a class property, so the component will not update when it changes. You need to store it as state on App
.
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
topWeakSlotsData: {
loading: true
},
lowWeakSlotsData: {
loading: false // or whatever data you want here
}
}
this._fetchWeeklyWeakSlots();
}
_fetchWeeklyWeakSlots() {
var _this = this;
fetch("...")
.then(function(response) {
return response.json()
}).then(function(json) {
_this._elaborateTopWeakSlots(json['return']);
}).catch(function(ex) {
console.log('parsing failed', ex)
})
}
_elaborateTopWeakSlots(data) {
this.setState({
topWeakSlotsData: {
loading: false,
options: data.options // or wherever else
}
}
}
render() {
return (
<HighchartContainer data = {this.state.topWeakSlotsData} container ="chart1" />
)
}
}
As the other answer points out you can refactor you _fetchWeeklyWeakSlots
method to use arrow/lambda functions, e.g.
_fetchWeeklyWeakSlots() {
fetch("...")
.then(response => response.json())
.then(json => json['return'])
.then(_elaborateTopWeakSlots)
.catch(ex => {
console.log('parsing failed', ex)
});
}
Upvotes: 3
Reputation: 226
Once your fetch promise resolves, you will need to update your state by passing your response to this.setState()
var _this = this
fetch(url)
.then( function(response) { return response.json() }) // parse our response into json
.then( function(json) { _this.setState({json: json}) } // set our state based on our parsed response
Once your state has been updated, you can reference {this.state.json} from within your component.
Bonus If you use ES6 arrow functions: args => { //do stuff here } you don't need var _this = this because of how this is handled.
The above example becomes:
fetch(url)
.then( response => response.json() )
.then( json => this.setState({ json: json })
Upvotes: 2