Reputation: 11788
I have state like below:
this.state = {
data: [ .... ]
misc: [ .... ]
}
I have button when clicked it will fetch data
.
the data
will be fetched using axios
and then setState
is used to replace the this.state.data
Then as per reactjs render will be called every time you setState to re-render the component if there are changes.
After this.state.data
is updated, and rendering is complete i want to run a function.
I dont want to run the function when misc
is updated. I only want to update when data
is updated
How to run a function after render only when this.state.data is changed
Upvotes: 0
Views: 5008
Reputation: 21161
You need to use componentDidMount()
, which will be called after a component is mounted (first render) and componentDidUpdate()
, which will be called immediately after updating occurs (but not for the initial render).
componentDidUpdate
takes 3 parameters: prevProps
, prevState
and snapshot. In your case, you can compare prevState.data
against this.state.data
to know whether data
has been updated:
class Main extends React.Component {
constructor(props) {
super(props);
this.counter = 0;
this.state = {
data: [],
misc: 'foo',
};
this.changeData = this.handleChangeData.bind(this);
this.changeMisc = this.handleChangeMisc.bind(this);
}
componentDidMount() {
console.log('componentDidMount!');
}
componentDidUpdate(prevProps, prevState) {
if (prevState.data !== this.state.data) {
console.log('componentDidUpdate and data has changed!');
}
}
handleChangeData() {
this.setState({
data: [...this.state.data, this.counter++].slice(-10),
});
}
handleChangeMisc() {
this.setState({
misc: this.state.misc === 'foo' ? 'bar' : 'foo',
});
}
render() {
return(
<div>
<button onClick={this.changeData}>Change data</button>
<button onClick={this.changeMisc}>Change misc</button>
<pre>DATA = { this.state.data.join(', ') }</pre>
<pre>MISC = { this.state.misc }</pre>
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById('app'));
.as-console-wrapper {
max-height: 106px !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
Upvotes: 0
Reputation: 3652
You could use componentDidUpdate (https://reactjs.org/docs/react-component.html#componentdidupdate). This is a lifecycle event that triggers every time the component updates, so you can check if the previous state of data is different than the current state. I'm assuming data is an array of objects, so to compare them you'll either have to use something to compare like _.isEqual from lodash, or what I've included below will work.
componentDidUpdate(prevProps, prevState) {
if(JSON.stringify(prevState.data) !== JSON.stringify(this.state.data)) {
// Execute your code
}
}
Upvotes: 1
Reputation: 4011
If I understood your question correctly you're talking about the use of lifecycle methods...
You should do your data fetching (ajax via axios or the native fetch api) in the componenetDidMount
lifecycle hook
Something like this:
componentDidMount() {
this.setState({ isLoading: true });
axios
.get(url)
.then(result => this.setState({ data: result.data, isLoading: false }))
.catch(error => this.setState({ error, isLoading: false }));
}
And your updating in componentDidUpdate
More info here: https://reactjs.org/docs/state-and-lifecycle.html
Upvotes: 1
Reputation: 391
If you want to restrict rendering on particular state change then just check for that state and return false else return true like:
shouldComponentUpdate(nextProps, nextState) {
if(this.state.misc != nextState.misc) {
return false
}
return true
}
Upvotes: 1