How to setState the props value in ComponentDidUpdate in react-native? - reactjs

componentDidUpdate(){
var date = this.props.navigation.state.params.selected_date
this.setState({
sleepinputs_date: date
})
}
When I try to setState the props value it throws an error "

You had created infinite state update.
Inside componentDidUpdate you update the state, when it updates the state, componentDidUpdate invokes again in this stuff keeps going without ending.

According to react docs, you will get an argument in componentDidUpdate. You can set state only if you use a conditional like the following.
componentDidUpdate(prevProps) {
// Typical usage (don't forget to compare props):
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
Basically you are comparing the old props with the new ones. Only if they are different, you can keep updating or modifying the value. If previous props are the same as current props, why you botter to set state them again.

Related

Change state using componentDidUpdate()

Hi i'm trying to change a state using componentDidUpdate() but I get an infinite loop.
componentDidUpdate(prevState) {
if (prevState.selectedOption1 !== this.state.selectedOption1) {
this.setState({ disabled2: false });
}
}
I canĀ“t figure it out
The componentDidUpdate function uses 3 parameters:
previous properties
previous state
snapshot (for when getSnapshotBeforeUpdate() is used.
You are treating the first parameter as previous state, which it is not, this results in your condition always being true and creating your infinite loop as setState is continually called.
To fix the issue correctly use the parameters of componentDidUpdate
componentDidUpdate(
prevProps, // This is the previous properties
prevState // This is the previous state.
) {
if (prevState.selectedOption1 !== this.state.selectedOption1) {
this.setState({ disabled2: false });
}
}
When you change the state, the component updates.
Thus, if you change state state when the component updates then you get your infinite loop.
If you insist on keeping this behavior then you might want to add a boolean check to your state.

Does getDerivedStateFromProps actually update state?

I've read the documentation on reactjs.org regarding getDerivedStateFromProps. I've seen the use cases. And I understand why to use it.
But I cannot figure out how it deals with the return value. Hence my question, when it does return... where does it go?
It doesn't setState because it does not have access to this.
To set state, requires using componentDidUpdate and looking for changes, then setting state.
Assume the following code:
public static getDerivedStateFromProps: IArrowFunction = (nextProps: IMyContainerProps, prevState: IMyContainerState) => {
if (nextProps.havingFun !== prevState.havingFun) {
console.log('[MyContainer.tsx] getDerivedStateFromProps :::::CHANGED::::::', nextProps, prevState);
return { havingFun: nextProps.havingFun };
} else { return null; }
}
So what does React do with that return ^?
I could then setState on componentDidMount. But this does not appear to have anything to do with getDerivedStateFromProps. Additionally this lifecycle method triggers every time. And it forces a re-render.
public componentDidUpdate(prevProps: IMyContainerProps, prevState: IMyContainerState): void {
if (prevState.havingFun !== this.props.havingFun) {
console.log('[MyContainer.tsx] componentDidUpdate *******CHANGED******', prevState, prevProps, this.props);
this.setState({ havingFun: this.props.havingFun });
}
}
At what point does the return from getDerivedStateFromProps come into play?
UPDATED: this lifecycle method will actually update state if properly configured as above. You do not need an additional method to setState
The return value is similar in concept like setState:
return { havingFun: nextProps.havingFun };
Where you can assume havingFun a state property and the value nextProps.havingFun is updated value.
When you use return null it means you are not doing anything with the state.
Note: getDerivedStateFromProps is really different concept than setState though I have tried here to explain it the way only.
You should read the docs for more detail:
getDerivedStateFromProps is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.
It's returned to state when the parent component re-renders.

Updating State with componentWillReceiveProps

I am looking at someone else code who updated the state of object in the react lifecyle:componentWillReceiveProps. I am fairly new to react and redux but thought that you do all the updating of state in the reducer useless its local state. Can someone tell me why he is doing it in componentWillReceiveProps? Thanks
componentWillReceiveProps(nextProps) {
if(this.props.isEditingbook && !nextProps.isEditingbook) {
let book = this.props.index.bookDictionary[this.props.currentbook.id]
book.name = this.state.model.name.value
}
this.setState({ ...this.state, ...nextProps})
}
Well, first of all, componentWillrecieveProps has been deprecated because it might cause some problems, take a look here . Instead, React docs point out that you should use componentDidUpdate which is a safe-to-use method.
And answering your question, if you looked a code where that person was using redux, then he used that deprecated method because when you bind a component to redux goblal state (store) through mapStateToProps, it's properties are bind to that component props. So, in other words, whenever the global state changes so does the component props, and if you want to "track" these changes in your component logic, you have to know when it's props are going to change, that's why you use componentWillRecieveProps or componentDidUpdate methods.
Here is how that example code should has been done with componentDidUpdate:
componentDidUpdate(prevProps) { //prevProps is the previous props of the component before being updated
//so, if this.props != prevProps it means that component props have been updated
if(this.props.isEditingbook && !prevProps.isEditingbook) {
let book = this.props.index.bookDictionary[this.props.currentbook.id]
book.name = this.state.model.name.value
}
this.setState({ ...this.state, ...prevProps})
}

`componentWillReceiveProps` explanation

I recently wanted to upgrade my knowledge of React, so I started from the component lifecycle methods. The first thing that got me curious, is this componentWillReceiveProps. So, the docs are saying that it's fired when component is receiving new (not necessarily updated) props. Inside that method we can compare them and save into the state if needed.
My question is: Why do we need that method, if changes in props of that component (inside parent render) will trigger the re-render of this child component?
One common use case are state (this.state) updates that may be necessary in response to the updated props.
Since you should not try to update the component's state via this.setState() in the render function, this needs to happen in componentWillReceiveProps.
Additionally, if some prop is used as a parameter to some fetch function you should watch this prop in componentWillReceiveProps to re-fetch data using the new parameter.
Usually componentDidMount is used as a place where you trigger a method to fetch some data. But if your container, for example, UserData is not unmounted and you change userId prop, the container needs to fetch data of a user for corresponding userId.
class UserData extends Component {
componentDidMount() {
this.props.getUser(this.props.userId);
}
componentWillReceiveProps(nextProps) {
if (this.props.userId !== nextProps.userid) {
this.props.getUser(nextProps.userId);
}
}
render() {
if (this.props.loading) {
return <div>Loading...</div>
}
return <div>{this.user.firstName}</div>
}
}
It is not a full working example. Let's imagine that getUser dispatch Redux action and Redux assign to the component user, loading and getUser props.
It 'serves' as an opportunity to react to the incoming props to set the state of your application before render. If your call setState after render you will re-render infinitely and that's why you're not allowed to do that, so you can use componentWillReceiveProps instead.
But... you are beyond CORRECT in your confusion, so correct in fact that they are deprecating it and other Will-lifecycle hooks Discussion Deprecation.
There are other ways to accomplish what you want to do without most of those Will-lifecycle methods, one way being don't call setState after render, just use the new incoming props directly in render (or wherever) to create the stateful value you need and then just use the new value directly, you can then later set state to keep a reference for the next iteration ex: this.state.someState = someValue, this will accomplish everything and not re-render the component in an infinite loop.
Use this as an opportunity to react to a prop transition before render() is called by updating the state using this.setState(). The old props can be accessed via this.props. Calling this.setState() within this function will not trigger an additional render.
Look at this article
the componentWillReceiveProps will always receive as param "NxtProps", componentWillReceiveProps is called after render().
some people use this method use this to compare nxtProps and this.props to check, if something should happen before the component call render, and to some validations.
check the react's documentation to know more about react lifecycle!
hope this could help you!
changes in props of that component (inside parent render) will trigger the re-render of this child component
You are absolutely right. You only need to use this method if you need to react to those changes. For instance, you might have a piece of state in a child component that is calculated using multiple props.
Small Example:
class Test extends Component {
state = {
modified: "blank"
};
componentDidMount(){
this.setState({
modified: `${this.props.myProp} isModified`
});
}
componentWillReceiveProps(nextProps) {
this.setState({
modified: `${nextProps.myProp} isModified`
});
}
render() {
return <div className="displayed">{this.state.modified}</div>
}
}
In this example, componentDidMount sets the state using this.props. When this component receives new props, without componentWillReceiveProps, this.state.modified would never be updated again.
Of course, you could just do {this.props.myProp + "IsModified"} in the render method, but componentWillReceiveProps is useful when you need to update this.state on prop changes.

Why not mutate state directly in componetWillReceiveProps

Does React recommend using setState in componentWillReceiveProps? Since componentWillReceiveProps is already occurring just before an update is rendered, I believe updating state in this portion of the lifecycle does not cause a 2nd re-render, it just changes the state along with the new props on the current update. So why not just mutate state directly? For example, why not do this:
componentWillReceiveProps (nextProps) {
this.state.title = nextProps.title
}
What are the drawbacks of the above or the advantages of using setState such as:
componentWillReceiveProps (nextProps) {
this.setState({title: nextProps.title})
}

Resources