I need to update a state in my react app while rendering the content. Is there any option to update state while rendering.
Note: I am very new to react
You can use componentDidUpdate() Lifecycle method.
and inside componentDidUpdate() function update your state.
FYI: componentDidUpdate() calls every time if component gets updtated.
https://reactjs.org/docs/react-component.html
Futureproofing Note: answer relevant to v16.4.
The answer to your question depends on what you mean by saying "while rendering".
When react invokes the render method of a component, it does not really render anything, yet. The results of the render method will undergo "reconciliation", which means that it will be compared to what's rendered at the moment. If a difference is detected, react will actually re-render the DOM, as effectively as it can.
This means that you can not do anything when react is actually rendering / re-rendering the DOM, since your code is not being executed.
You can, however, do something after the render method has been invoked.
As others have stated before me, the componentDidUpdate method is the place.
Note that the fact that this method has been invoked does not necessarily mean react has re-rendered the DOM. It only assures that the component is in sync with the DOM.
Do note that since setting state CAN cause a re-render, so you should really be careful about setting state in componentDidUpdate - or you might cause an infinite loop of sorts.
Even if you correctly implement shouldComponentUpdate, stopping the render cycle from ever reaching cDU- react docs suggest the result of sCU can be taken as a hint in the future, which will break your app in future releases.
So, if you must setState in cDU - you must check that this setState is required, and is not a side-effect of setting the state in the first place.
Related
An example of the issue is found on CodeSandBox. Am I short circuiting myself between TRUE/FALSE values?
Can someone please help explain why the state variable isOptionOne is not being set as expected? Upon calling setIsOptionOne I would think that I can use isOptionOne in the remaining lines of code of the function. Unfortunately, that does not seem to be the case. To verify, see the console.log output. The two values for isDefault and isOptionOne should match.
Where am I going wrong? Thank you.
That is the expected behavior. React batches the state updates, which means it doesn't immediately update the state and re-render everything after each setState method call. From official documentation:
setState() enqueues changes to the component state and tells React
that this component and its children need to be re-rendered with the
updated state. This is the primary method you use to update the user
interface in response to event handlers and server responses.
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.
setState() does not always immediately update the component. It may
batch or defer the update until later. This makes reading this.state
right after calling setState() a potential pitfall. Instead, use
componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update
has been applied. If you need to set the state based on the previous
state, read about the updater argument below.
Additionally, the above document is for the traditional class component's setState API. If you want to detect a change in your hook-based state, use useEffect.
A component will rerender when one of its props changes. That's sort of the whole point of React.
A component that's subscribed to a slice of Redux state will rerender when that state changes. That's sort of the whole point of Redux. And when you use the connect api, those slices of state are simply props, so it goes straight to my first point.
SO, what I'm wondering is:
// only executes once, on mount, right?
componentDidMount() {
this.something()
this.props.someReduxActionThatModifiesAnotherPropInThisComponent()
this.somethingElse()
}
Since the redux action changes the prop, and the component rerenders, I would think that componentDidMount has had its day and now it's done, and we'll never run this.somethingElse().
Obviously I am wrong about this. I know. Can someone tell me what it is that makes this work? What is the whole flow here? I imagine the answer is maybe simply that a component doesn't rerender from inside CDM?
And is it any different in useEffect?
You are correct that componentDidMount only runs once. You are also correct that dispatching a redux action from within the method will trigger a re-render if your component is subscribed.
I think the confusion is about when a re-render occurs.
Updating state only informs React that a re-render is required, it does not pause execution and re-render immediately.
Because of this, the lifecycle method will complete execution of the entire method, and the run the scheduled re-render after.
This is related to why you also cannot use the updated state immediately after calling this.setState (or dispatch in Redux). Because the state is not updated instantly, you've only informed it that an update is required. Behind the scenes, React batches and performs the updates, and then determines what re-renders to perform.
The same is true about Function components and useEffect.
componentDidMount runs only once during the mounting process. But even if you replaced componentDidMount with componentDidUpdate, it also wouldn't rerender before executing the whole function.
The reason to this is that it is actually up to React when to re-render. Sometimes, in situations like yours, React decides not to re-render the component immediately and postpone it.
A similar situation would be when same setState functions are called inside a method. The first setState call doesn't force an immediate re-render.
I am currently developing a react redux based web application which displays large amount of data on the UI. When the data size increases, the frame per second decreases. Also, certain forms displaying components take longer and appear to be sluggish.
If someone could guide me on correct rendering method or some coding standards needed to be followed for such applications, it will be a great help.
-Thanks
I am currently checking whether my application uses react lifecycle components (explicitly by any other developer). I am also suspecting the way in which components are rendered.
Hello and welcome to StackOverflow!
Your question is very generic, so it's hard to pinpoint exactly how to resolve it.
I guess the first thing I'd do is take a look in chrome's performance tab in the developers tools. You can use it to profile you application and see what functions take the longest.
You can find helpful information here and here.
This will give you a good starting point.
As far as profiling a React application, you can take a look at React's Dev Tool profiler, more info can be found here.
You might also want to make sure to avoid the deprecated lifecycle functions, as they are known to cause performance issues. Those are:
componentWillMount
componentWillRecieveProps
componentWillUpdate
And make sure you perform all HTTP requests after components mount.
If everything fails, you should look into memoization techniques. Memoizing is basically saving the result of a function call in memory, so the next time your function is called with the same arguments, you don't recalculate the output. For that you can use React's builtin memo feature to memoize complete components, and a selector (like reselect) to memoize redux computations.
Please Check Prevent Unnecessary Rendering
All children in component re-renders when its props or state gets updated. This is the default behavior, and, since React updates only the relevant DOM nodes, this process is usually fast. However, there are certain cases where the component’s output stays the same regardless of whether the props have changed.
To alter the default implementation, you can use a lifecycle hook called shouldComponentUpdate(). This lifecycle hook doesn’t get invoked during the initial render, but only on subsequent re-renders. shouldComponentUpdate() is triggered when the props have changed and it returns true by default.
shouldComponentUpdate(nextProps, nextState) {
return true;
}
If you’re sure that your component doesn’t need to re-render regardless of whether the props have updated or not, you can return false to skip the rendering process.
class ListItem extends Component {
shouldComponentUpdate(nextProps, nextState) {
return false
}
render() {
// Let the new props flow, I am not rendering again.
}
}
Alternatively, if you need to update only when certain props are updated, you can do something like this:
class ListItem extends Component {
shouldComponentUpdate(nextProps, nextState) {
return nextProps.isFavourite != this.props.isFavourite;
}
...
}
For example here, we’re checking whether the current value of isFavourite has changed before each render (nextProps holds the new value of the prop) and if yes, the expression returns true. The component gets re-rendered. The changes in any other props won’t trigger a render() since we’re not comparing them in shouldComponentUpdate().
Attention Replacing ‘componentWillReceiveProps’ with ‘getDerivedStateFromProps’
With the release of React 16.3, some new lifecycle methods have been
introduced, and release of React 17 will deprecate some lifecycle
method.
You can find helpful information here
Will componentWillMount run again if component is re-rendered because of parent component?
No, componentWillMount is called only once.
Also, componentDidMount is called only once.
componentDidUpdate is called on every re-render.
To correctly understand about the react lifecycle methods you can go through this link.
https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1
The short answer is NO
It's called once right before your component is about to be rendered to the DOM.
The long answer is:
componentWillMount
Your component is going to appear on the screen very shortly. That chunky render function, with all its beautifully off-putting JSX, is about to be called.
Most Common Use Case: App configuration in your root component.
Can call setState: Yes, but don't. Use the default state instead.
componentDidMount
Here is where you load in your data. ComponentDidMount is also where you can do all the fun things you couldn’t do when there was no component to play with. Basically, here you want to do all the setup you couldn’t do without a DOM, and start getting all the data you need. Most Common Use Case: Starting AJAX calls to load in data for your component.
componentWillReceiveProps
Perhaps some data that was loaded in by a parent component’s componentDidMount finally arrived and is being passed down. Before our component does anything with the new props, componentWillReceiveProps is called, with the next props as the argument.
shouldComponentUpdate
shouldComponentUpdate should always return a boolean — an answer to the question, “should I re-render?” Yes, little component, you should. The default is that it always returns true. It's an awesome place to improve performance.
componentWillUpdate
Most Common Use Case: Used instead of componentWillReceiveProps on a component that also has shouldComponentUpdate (but no access to previous props). It’s basically the same as componentWillReceiveProps, except you are not allowed to call this.setState.
componentDidUpdate
Here we can do the same stuff we did in componentDidMount — reset our masonry layout, redraw our canvas, etc. Basically, we use it when it's all said and done, but we don’t want to waste time to redraw the canvas every time it updates. Most Common Use Case: Updating the DOM in response to prop or state changes.
componentWillUnmount
Here you can cancel any outgoing network requests, or remove all event listeners associated with the component. Basically, clean up anything to do that solely involves the component in question — when it’s gone, it should be completely gone.
I have been reading the React docs and came across shouldComponentUpdate(). My understanding is that everytime setState() is called, a re-render of that component will be updated.
My question is that If the value to be updated is the SAME as the current state value, would this trigger a re-render event? or I would have to manually checks for the current value and value to be updated in shouldComponentUpdate()
The official React documentation states:
The default behavior is to re-render on every state change...
https://reactjs.org/docs/react-component.html#shouldcomponentupdate
This means that by default, render() will be executed if any of a component's state or props values changes.
You can override this default behavior using shouldComponentUpdate(). Here's an example that only updates if a state value changes.
shouldComponentUpdate(nextProps, nextState) {
return this.state.someValue !== nextState.someValue;
}
Note: this example completely ignores props. So, any changes to props will not trigger render().
Adding more to #Jyothi's answer regarding implementing shouldComponentUpdate() to skip unnecessary re-renders, in React 15.3 they introduced a new concept PureComponent. From reactjs docs
The difference between them is that React.Component doesn’t implement
shouldComponentUpdate(), but React.PureComponent implements it with a
shallow prop and state comparison.
This allows to skip unnecessary calls of render in class components by just implementing PureComponent instead of the usual Component. There are a few caveats with PureComponent though, from the docs about React.PureComponent’s shouldComponentUpdate():
... only shallowly compares
the objects. If these contain complex data structures, it may produce
false-negatives for deeper differences.
... skips prop updates for the whole component subtree. Make sure all the
children components are also “pure”.
Usage of PureComponent can in some cases improve performance of your app. Moreover, it enforces you to keep state and props objects as simple as possible or even better, immutable, which might help simplify the app structure and make it cleaner.
I dont know if I understood your question correctly but react only re renders when there is difference between virtual dom and real dom.
And as Jyothi mentioned in his answer that render method will be called irrespective of the value passed in the set state function but rerendering will depend on what this render method returns.
In functional components, calling setState() with the equal value won't cause a rendering, while in a class component it does: https://dev.to/sunflower/reactjs-if-it-is-setting-a-state-with-the-same-value-will-the-component-be-re-rendered-5g24
Note that we're just talking about virtual (React) renderings here. Brower-rendering won't happen in any case - i.e. neither in the functional component nor in the class component - as long as the state (or to be more precise: the effective DOM) doesn't change.