Warning about calling setState on an unmounted component - reactjs

The warning:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the _class component.
Any idea where it can come from. Gotchas or things like that ?
I already looked at all the setState in my code and replaced them to make sure. Can't find where it comes from...
My observations so far:
Only happens in my tests
No problem in the browser
I thought I had more... but with more testing I got all confuse because it didn't fit the patterns I thought I understood...
So ! I understand what the error is but this time the warning is about a _class component so I'm lost... I just upgraded to react-router v4 and it needed a lot of changes so it's hard to localize the source of the warning.
Anyone had had a similar problem before ?
EDIT:
I found the setState that were causing problem. It was in react-router-server. I'll look into it to see if I can fix it !
Thanks #zerkms for the idea to look with a debugger to get the line number since there was no trace in the terminal.
I used the v8 experimental inspector(https://stackoverflow.com/a/39901169/3687661). Works pretty good :)

This is common due to async activities like API calls. For example, this happen when you try to set a state after you receive the data from the server and the corresponding page to receive that state is not mounted.
To avoid this, check if the component is mounted before setting state in that component. Use a flag to check, say this.mounted = true in componentDidMount and change the flag to false in componentWillUnmount. Use this.mounted across the component to check if the component is mounted. This will fix the warning.
Hope this helps!

This usually happens when you call this.setState within a setTimeout or setInterval or some other deferred function.
If you are using setTimeout/setInterval make sure you call clearTimeout/clearInterval in componentWillUnmount.

Related

Is ResizeObserver API necessary or preferred in React?

We can already detect dimension change by using ref and useEffect in React:
useEffect(() => {
console.log("height changed to", ref.current?.clientHeight)
}, [ref.current?.clientHeight])
I wonder what is the advantage of ResizeObserver over this ref + useEffect approach? I'm surprised there's no online discussion around this, given ResizeObserver has been there for awhile since 2018. I can see if you're using Vanilla Javascript then ResizeObserver might be the best way to get dynamic height.
But in React I just don't understand how ResizeObserver API is better. I tested both and in Chrome both fire updates almost at the same time. I researched online and many are talking about how to use React Hook with ResizeObserver, but rarely do these posts talk about ref + useEffect already suffice.
Does anyone know if using React, any advantage using ResizeObserver API, or it really doesn't differ much from ref + useEffect approach?
We can already detect dimension change by using ref and useEffect in React:
For a useEffect to run, the component must be rendering. For the component to be rendering, something somewhere must have set state. So if all of that is happening, then yes, your effect can notice the size has changed since the previous render.
But if nothing sets state, then none of that will happen. Maybe you're getting lucky, and some component happens to be setting state around the time the size changes, but that's not something you should rely on. If you delete some random component, or try to optimize performance by skipping rendering, you can suddenly break your resize "detection" code.
The point of the resize observer is to get notified that the change has happened. Then you can set state, and cause the rerender. So now instead of hoping a rerender happens, you know it will happen.

Possible cause and solution for this warning

Warning : Cannot update a component (X) while rendering a different component (Y). To locate the bad setState() call inside Y, follow the stack trace as described in :
There are suggestions on this document. It looks like the same warning.
doc door
It is supported to call setState during render, but only for the same component. If you call setState during a render on a different component, you will now see a warning:
Warning: Cannot update a component from inside the function body of a different component.
This warning will help you find application bugs caused by unintentional state changes. In the rare case that you intentionally want to change the state of another component as a result of rendering, you can wrap the setState call into useEffect.

React check how many times a component re-renders

I'm working on something and a piece of my code is a bit slow, what I think happens is that the component re-render too many times for no reason.
Is there any way to check how many times a component re-renders in react(or react-native for the matter)?
What i've tried to do is put a console.log after the render method and count how many there are but i'm not sure if that would work.
Thanks in advance!
you can place console.count('counter') in your render function to check this. Here you'll find all the details about console.count link
console.log will work, if you place it within your render function. If you're concerned about a component re-rendering too many times, try extending React.PureComponent. Info about PureComponent can be found in React's docs. You could also look into the shouldComponentUpdate method to see if that will help solve your re-rendering. Info about that is also in their docs. Good luck!
Better than putting console.log in every component is to use this small util
https://github.com/maicki/why-did-you-update
You will be warned in console every time component re-rendered needlessly (e.g. props nor state did change)
Even though it's not maintained anymore it works perfectly.
Best regards

React state update while rendering

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.

forceUpdate VS forceReload

I'm wondering what is the difference between forceUpdate() and forceReload() in ReactJS.
Tried to find some documentation about that but couldn't find some on forceReload()-
Thanks in advance!
Not sure where you saw it, but forceReload isn't a part of React. You presumably couldn't find documentation because there isn't any -- if I search for "forceReload" react right now, this question comes up first.
If you want to make a component rerender without changing its state or props, you should call forceUpdate.

Resources