I guess this is a simple question but here goes: Is there a way of instructing your component to re-render when the props change? I have my component connected to the redux store which on a certain action updates the state, which then filters down into the props, upon which point I want the app to respond to the changes.
I guess you would use componentDidUpdate()?
Something like:
// ...
componentDidUpdate(prevProps, prevState) {
if (prevProps !== this.props) {
// re-render x <-- not sure how to do this
}
}
Plus what would be the method to re-render the whole component, and what would be the method of re-rendering only the updated props?
Any help appreciated.
You can call this.forceUpdate() in the method. Another way is this.setState(this.state).
You can use
componentWillReceiveProps (props){
this.doSomething(props) // To some function.
this.setState({data: props}) // This will update your component.
}
If your props is something that needs to change the state you will get an infinity loop.
Check out Reacts life cycle here by the way, might help aswell.
Related
My parent component sends a prop called array and if this prop changes, I want the child component to re-render with the new prop.
So here is what I added in my child component:
componentDidUpdate = prevProps => {
if (!isEqual(prevProps.array, this.props.array)) {
this.setState({array: this.props.array});
}
};
It seems to be working, although I'm wondering if I thought too much and there's an easier way. Someone suggested If they're equal, couldn't you update the state with the new array anyway? earlier but I wasn't quite sure what that meant and haven't been able to get clarity. Any suggestions?
In React, the Child component should render in case there is a change in its props, so this code in componentDidUpdate is not necessary as the component will re-render on its own.
And if you also want to update a state then this piece of code is fine in that case. Although it's recommended to not have the props and state with the same name.
I was using the componentWillReceiveProps lifecycle event to enable or disable transition to the next page. Now that this event is changed to UNSAFE_componentWillReceiveProps, I feel like I shouldn't use it anymore, however I couldn't find an obvious replacement for it.
The location of the component comes from props.location.pathname, so I'd need an event, where I can access both the previous and next props and then set the initial appearance of the component depending on if there should be transition or not, however:
getDerivedStateFromProps only has access to the previous props.
shouldComponentUpdate should be used for telling the component if it should update or not, which is not what we want, so it's out.
render doesn't have the previous props.
getSnapshotBeforeUpdate passes the parameter to componentDidUpdate, at which point the component is already rendered, so I can't set the initial apprearance.
I guess I could save the previous pathname and use that the next time in render, but this doesn't seem like an elegant solution. What is the best practice in this situation?
You stated that
getDerivedStateFromProps only has access to the previous props.
But getDerivedStateFromProps has access to next props and previous state
Saving the previous pathname may not seem elegant, I agree, but it is an alternative offered here: https://codesandbox.io/s/rjyvp7l3rq found here https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html.
Take a look at the uncontrolledEmailInput component saving prev props in state
state = {
email: this.props.defaultEmail,
prevPropsUserID: this.props.userID
};
static getDerivedStateFromProps(props, state) {
// Any time the current user changes,
// Reset any parts of state that are tied to that user.
// In this simple example, that's just the email.
if (props.userID !== state.prevPropsUserID) {
return {
prevPropsUserID: props.userID,
email: props.defaultEmail
};
}
return null;
}
Here is a great article about the new lifecycles: https://medium.com/#baphemot/understanding-react-react-16-3-component-life-cycle-23129bc7a705
You can use below which is Safe and recommend by Reactjs
componentDidUpdate(prevProps) {
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
As per react documentation you should use componentDidUpdate. It has access to prevProps, prevState and current props, state in this.props, this.state.
Take a look at the documentation
https://reactjs.org/docs/react-component.html#componentdidupdate
componentDidUpdate(prevProps) {
if(this.props.pathname !== prevProps.pathname) {
//do something here or setState to adjust the appearance accordingly
}
}
I'm trying to update a child component as soon as it recieves new props. However, componentWillReceiveProps() in my child component is called before the props have actually updated. After reading this article i do understand why but it doesn't explain me how to solve my problem.
How do i call componentWillReceiveProps() after the props have updated?
Right now i'm cheating my way around it by letting a timeout run which waits for the actual update, but i really don't like this solution.
componentWillReceiveProps(){
var timeOut = setTimeout(() => this.loadPosts(), 100)
},
Thanks id advance!
Is it necessary to call componentWillReceiveProps after the props have updated? Or can you use the nextProps argument?
Eg. if you rewrite as:
componentWillReceiveProps(nextProps){
this.loadPosts(nextProps)
},
and then of course also rewrite the signature of loadPosts to allow manually passing in props:
loadPosts(props = this.props){
// do something with props
...
}
Use componentDidUpdate(prevProps, prevState). When it's called, two arguments are passed: prevProps and prevState. This is the inverse of componentWillUpdate. The passed values are what the values were, and this.props and this.state are the current values.
I'm new to React and am trying to update the state of a parent component from the child everytime an onChange action happens. The onchange action comes from an input box that when letters are typed it updates the state of searchInputVal with the value of what has been typed. I have a parent <App/> component with the following properties and states here:
updateSampleFilteredState(filteredSamples) {
this.setState({
samples: filteredSamples
});
},
getInitialState () {
return {
samples:allSamples,
searchInputVal:""
}}
I pass the properties and states down to a child component here:
updateNewSampleState(filteredSamples){
return (
this.props.updateSampleFilteredState(filteredSamples)
)
}
render() {
const filteredSamples = this.props.samples.filter(sample => {
return sample.sampleFamily.toLowerCase().indexOf(this.props.searchInputVal.toLowerCase()) !== -1;
});
this.updateNewSampleState(filteredSamples);
return <div className="samples-container-inner-styling">
{
filteredSamples.map((sample) => {
return (...
Before I added the line this.updateNewSampleState(filteredSamples); the child component would render out the filtering just fine but obviously not update the state of sample with the new filtered state. When I the line this.updateNewSampleState(filteredSamples); to execute the function in the component to set the new state I get a list of re-occuring errors that eventually make my app crash. The errors say something about an anti pattern. I'm not sure how else to update the state?
You should't be updating the state from the render function, and you are facing the reason why that's a bad way to do things. Every time you call the setState the component re-renders, so if you call it inside the render function it will be called again and so on... You should ask yourself why are you calling that function there. I guess you could just do it in the onChange function you are using for the input.
As already mentioned by #César, setting the state in the renderer doesn't make sense, since setting the state triggers a rerender of the component, so you basically get something like an infinite render loop.
Given that you are computing filteredSamples only from the props, you could compute that state in the constructor:
The constructor is the right place to initialize state.
However, note the following when deriving state from props in the constructor:
It's okay to initialize state based on props if you know what you're doing. [...]
Beware of this pattern, as it effectively "forks" the props and can lead to bugs. Instead of syncing props to state, you often want to lift the state up.
If you "fork" props by using them for state, you might also want to implement componentWillReceiveProps(nextProps) to keep the state up-to-date with them. But lifting state up is often easier and less bug-prone.
render() function will fire when this.props.location.query.someQuery updated. But I do not want re-render the component when updated query.
The way I updated query is following:
this.props.location.query.someQuery = otherValue;
hashHistory.replace(this.props.location);
Take a look at the react lifecycle.
You should implement a method called shouldComponentUpdate().
Use this as an opportunity to return false when you're certain that the transition to the new props and state will not require a component update.
This method will be called each time React thinks your component should update, if you don't want it to re-render under certain conditions, check for those conditions and then return false in this function.