How to find out what is initiating an (re)render in React - reactjs

How can you trace what action, state change or dom manipulation is initiating a (re)render?
I'm using TransitionGroup to animate with JS, however before the callback of componentWillLeave(callback) is called, the page re-renders and I have no idea why. What kind can initiate a full page rerender beside forceUpdate() and state change of the top level component?

You can use the lifecycle method componentWillUpdate which fires just before a component is re-rendered due to a change in props or state:
componentWillUpdate(nextProps, nextState) {
// Inspect nextProps and nextState to see what triggered this
}

Related

What happens to the state of a react component when the component is re-rendered?

What happens to the state of a react component when the component is re-rendered?
Does it remain unaffected, or does it get reset to some 'default' value? Why?
When you refresh the page, components get re-rendered and state get's reset to default value is it because when component re-rendered we have following lifecycle of react that runs
Initialization here react constructor() run and set the state to default value
Mounting
componentWillMount() , componentDidMount()
Updation
componentWillRecieveProps(), shouldComponentUpdate(), componentWillUpdate(),componentDidUpdate()
Unmounting - This run when you are leaving the component
componentWillUnmount()
The state does not depend on the rendering of a component and remains unaffected by re-rendering.
The state gets updated only by a lifecycle method or by a call to setState.
Change in the state will re-render with an updated state.
A state can be changed either by user interaction or a life cycle method only.
When a state is changed, only the updated part will be rendered

`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})
}

Will setState inside componentWillReceiveProps run before render?

The react docs mention that calls to setState are enqueued, and do not happen immediately. Does react make any guarantees that setState enqueued inside componentWillReceiveProps will execute before the next component render? Are either of these scenarios more likely than the other?
props change > componentWillReceiveProps called > setState enqueued > setState runs > render (which includes new state)
props change > componentWillReceiveProps called > setState enqueued > render > setState runs > re-rendered
Or, are both of these scenarios equally likely? Meaning does React not make any guarantees when setState will run relative to component lifecycle methods?
Here is a ES2015 code excerpt of my example:
import React from 'react';
class Widget extends React.Component {
componentWillReceiveProps() {
this.setState({foo: 'bar'});
}
render() {
return <div>
<a onClick={(e) => {
e.preventDefault();
this.props.triggerExternalPropsChange();
}}>
Click me to trigger new props
</a>
</div>;
}
}
Where triggerExternalPropsChange passes new props to the Widget component.
The only reason componentWillReceiveProps exists is to give the component an opportunity to setState. So yes, any state you set synchronously in it will be processed together with the new props. There won’t be two renders in this case, just one.
It's 1.
Calling setState() in componentWillReceiveProps() is an exception in the sense of executing state update before the component renders, so you will get both props changes and state changes applied in the same render.
Yep, both are likely. React will try to render anytime it gets new props or state and because it does dom diffing, it tries to render as often as possible. You have options to control it though, using shouldComponentUpdate you can check and wait until both props and state have been updated before rendering.

Where can I redirect to a different page in React-router 1.0

render(){
if (!this.readyForStep()){
this.props.history.pushState(null, `step2`);
}
// Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.
}
So I can't redirect in render()... where in a component lifecycle can/should I?
Depending on the specific semantics you want redirecting before or after render, you can make this check in any of componentDidMount, componentWillReceiveProps, or componentDidUpdate.
Synchronous transitions lead to state updates in the <Router> component, so you can't make them in any place where you normally couldn't call setState.

Resources