React, componentWillReceive lifeCycle Hook not being invoked (on passing props) - reactjs

I was trying to pass props both in App component (The root Component) and then to Header component from App itself.
I have used Life Cycle Hooks upto componentWillReceiveProps() in both App and Header Component.
componentWillMount(), render(), componentDidMount() are getting executed in both the Components in an expected order.
However, componentWillReceiveProps() is not executed at all even on passing props. This is a unExpected behaviour, since componentWillMount() was executed normally!
I shall be extremely thankful to know why is this happening ! Thank you :)
Kindly check the code sample from the below link:
https://codesandbox.io/s/r092xkpwjp
Please Note: Question has been updated, and it shows both scenarios now, new props being passed (in Header Component which works fine now) and no new props being passed as was previously the case in the question (in App Component which still shows why things were working unexpectedly).

I don't see why you expect your components to be updated as the The props being passed to them always stay the same and no new props have been passed to these at all, but generally you should use componentDidUpdate(prevProps, prevState).
componentWillReceiveProps() only gets invoked when the props passed to them are new props, different from the previous values. In the question this was not happening.
Note: The question has been updated now for it to work properly.
Also consider managing the state by static getDerivedStateFromProps(props, state), i.e.:
static getDerivedStateFromProps(props, state){
// just return the state
return {
isLoading: false,
money: props.money
}
}
- it's executed on init + on updates.

As stated in the official documentation (see https://reactjs.org/docs/react-component.html) the
componentWillReceiveProps()
lifecycle method is deprecated and should be avoided.
The reason why it is never called is that, to help user avoid it, React developers renamed it
UNSAFE_componentWillReceiveProps()
You should however avoid it, since they plan to deprecate that method

1.The main reason why the componentWillReceiveProps() was not being invoked was because my props passed to Header Component were not changing at all, I have been passing the same props again and again. And componentWillReceiveProps() gets executed only when the props being passed are different each time.
This is what my Header component looked at the time of asking this question.
<Header
menus={["home", "about", "services", "blog"]}
/>
The Header Component had only the menus prop as an array (at the time of asking this question) and no event was updating this menus prop , that's the reason why my
componentWillReceiveProps() was never invoked/called in the Header Component.
Note: To simply the things I now passed another prop to Header Component, and started to test my code on this prop instead of working with the array menus prop.
<Header
menus={["home", "about", "services", "blog"]}
prop={this.state.prop}
/>
And I am making my state.prop to update using an event handler:
// Dynamically sending Props
handlePropSending = () => {
this.setState({
...this.state,
prop: this.state.prop + 1
});
};
And as I am clicking on the button 'Sending Props to Header', the new props are sent to Header Component and our componentWillReceiveProps is being called and executed succefully.
And same was the issue with componentWillReceiveProps in the App Component
ReactDOM.render(, rootElement);
Since I was adding money prop (money={9199}), there actually is no Parent Component available for money prop to update it's value (which we could have passed to the App Component for it to invoke its componentWillReceiveProps method).
NOTE: The code is updated now and there are event handlers now to make sure the props keep updated and now the componentWillReceiveProps() method is indeed being successfully invoked.
componentWillReceiveProps demonstrated along with other life Cycle Hooks
LIKE THEY SAY :) ALL IS WELL THAT ENDS WELL :)

Related

ReactJS - componentWillReceiveProps uses

I started to learn ReactJS I would like to know what are the scenario to use componentWillReceiveProps? what is the purpose for using it?
Currently i'm using props without it, is there any impact ?
In cases where you want to take action in child component in response to props change, componentWillReceiveProps was supposed to the right candidate. Example of it is when you have a user component which calls and API to fetch the user details based on an ID that is provided by its parent and anytime the prop ID changes, you would want to trigger the API call again and re-render the updated view.
However, componentWillReceiveProps is called on every parent re-render and not just prop change, so while you are using it, you must provide a conditional check between previous and currentProps like
componentWillReceiveProps(nextProps) {
if(nextProps.id !== this.props.id) {
//API call goes here
}
}
However from v16 onwards, its discouraged to use componentWillReceiveProps and instead its usage is split into componentDidUpdate which is where you can make API calls and getDerivedStateFromProps or memoized functions or key updates in order to make state change based on prop change.
Please check componentWillReceiveProps vs getDerivedStateFromProps for more details
If your component accept some props and if on change of that props you would like to do some business logic or state change, componentWillReceiveProps is the lifecycle method where this logic should go, as every time props changes componentWillReceiveProps is called.

componentDidUpdate called twice every route change

In my application i have a HomePage component which has navlinks in it. the route for this component is <Route to="/browse/:item" exact component={HomePage} />. so the component has a navigation bar with NavLink links to "sub routes" of it. for example a NavLink that leads you to /browse/featured or
/browse/new and i added to this component the lifecycle method componentDidUpdate() to just console.log("UPDATED HOMEPAGE") and whenever i click a NavLink this happens:
i tried to use shouldComponentUpdate with the nextProps and nextState params to see if indeed the state or props are changed (something that will cause a re-render) but they stay the same.
Thanks in advance for your help.
EDIT:
the code is on github https://github.com/idanlo/spotify-test-frontend
components that have the problem that i have seen are AlbumView and HomePage
ANOTHER EDIT:
this is a console.log() of the two updates happening, each one displaying the props before and after the update. on the first update you can see that the url is different so the update is supposed to happen but on the second update nothing is different, everything is the same (in the state everything is the same too)
Usually there are multiple calls because of changes made to the state. Check other files to make sure that no actions that modify the state are initially called. Even though you check for differences for nextProps, the variable that changes might not be in props.
I suspect that Navlink's internal implementation uses setState with an updater function which is the source of this duplicate log
I found that when I update state with an updater function then componentDidUpdate gets fired twice!
However when I pass an object to setState - componentDidUpdate is fired only once.
setState(updater[, callback])
example:
incrementScore = () => {
this.setState(prevState => ({
score: prevState.score + 1
}));
};
VS
setState(stateChange[, callback])
example:
this.setState({quantity: 2})
I guess it's because
Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately.
read about setState on React Docs

when does the `render()` method in react get called

As far as I know these are the scenarios when react calls the render() method provided shouldComponentUpdate() is not implemented.
when your component get mounted initially
when state got changed using this.setState()
when your component receives new props
when this.forceUpdate() get called.
Is there any other scenarios that I am missing?
Yes there's one more case I can think of. When parent component is re-render.
Every time a component is re-render all its children get re-render too. Unless you implement shouldComponentUpdate method in the children.
Hope it helps.
when context gets changed render gets called

Does my component need force update to scrollIntoView?

I'm making my first react + redux app and I have a question. I have a component that render a input field and, as some content is added above it, I need it to scrollIntoVIew.
So, I just added the scrollIntoView in the component componentDidUpdate() lifecycle method :
componentDidUpdate() {
console.log("scroll");
this.refs.input.scrollIntoView();
}
The only problem is that this component does not re render each time (as nothing change in it) so the scrollIntoVIew is called only one time.
I could force update to component but this is not really good practice isn't it ? What can I do in this case ?
You could call setState and update some object in the component's state every time content is added to re-render the component, and componentDidUpdate will be invoked.
You could also use the second argument (callback) to setState, but the React docs say the following about second argument of setState:
The second parameter is an optional callback function that will be
executed once setState is completed and the component is re-rendered.
Generally we recommend using componentDidUpdate() for such logic
instead.

React componentWillMount() called after componentWillUpdate()?

I am in the process of trying to debug a third-party component. What I see happening is that it expects to initialise an internal attribute in componentWillMount() and then make use of it in componentWillUpdate(). The React documentation says this about 'update' methods:
An update can be caused by changes to props or state. These methods are
called when a component is being re-rendered
That being said, should the code handle the possibility that componentWillUpdate() will be called before componentWillMount() or should I be digging to see what seems to be apparent cause of the inverted sequence?
We are using React 15.0.1
As you mentioned componentWillUpdate() will be called only when a component is being re-rendered. And componentWillMount() will be called right before the initial render (a component is mounted just once in its lifecycle). So there are no possibility componentWillMount() is called after componentWillUpdate().

Resources