1st premise:
componentDidMount() is invoked immediately after a component is mounted (inserted into the tree).
2nd premise:
You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state.
both from https://reactjs.org/docs/react-component.html#componentdidmount
My conclusion:
Based on the above, mounting cannot be the last step in displaying to the browser, otherwise what is rendered and mounted (any intermediate state) before componentDidMount will always be shown.
However, based on my experience, I've found that any state specified in the constructor does in fact get shown before any overriding state changes in componentDidMount.
This is suggesting to me that premise 2 is incorrect. My conclusion is therefore incorrect as well. Mounting must be the final step in displaying to the browser.
Can anyone clear this up for me?
I believe if you set the state in componentDidMount synchronously, the new state will be the only one shown (or at least the switch would happen so fast after rendering it would be impossible to detect).
If you're trying to set it asynchronously, such as using results from a fetch, then you would see the initial state until the async call is completed.
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.
I have for a long while assumed that code I put inside the componentDidMount life cycle method gets called only if the component is mounted. But now I am being told that it might not be the case at all times. For instance, while I am fetching some data inside the componentDidMount method, a user could navigate to another component and cause my component to unmount. And when the data fetching is done, they tell me, the line of code after the data fetching continues naively executing as if the component is still mounted, and that causes some nasty error. Isn't it react's job to ensure that my code doesn't run when my component is unmounted, and resumes only when it is mounted?
UI-programming in general must be asynchronous, such that pressing button doesn't freeze the entire visuals. Therefor flexibility must be left in the framework, like not halting everything just to wait for lifecycle methods. This is the programmers job. API just promises that componentDidMount is called at certain point, nothing else.
If you anticipate long running process in componentDidMount, you could periodically check for instance if componentWillUnmount has been called and if so then cancel execution.
As much as I know, this are the "phases" on a react lifecycle for a component:
Mounting: Mounting is the stage of rendering the JSX returned by the render method itself.
Updating: Updating is the stage when the state of a component is updated and the application is repainted.
Unmounting: As the name suggests Unmounting is the final step of the component lifecycle where the component is removed from the page.
mounting -> updating -> unmounting
I succesfully used it, but i don't know how to mix those 3 "phases" with :
- commit phase
- precommit phase
- render phase
I found this : http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
I'm not sure if "mounting", "updating" and "unmounting" are phases or somethings else. Can it be the case that phases are: commit, precommit and render. And "mouting, updating and unmounting" are events or stages ?
Any clues?
The "render phase" and "commit phase" are descriptions of the internal process that react goes through to update your page. While it can be useful to understand what's going on in these, the only place you can interact with it is through the various lifecycle hooks, such as componentDidMount, componentDidUpdate, and componentWillUnmount, so those are the things i would recommend you focus your research on.
When it's time to render the page (usually caused by calling this.setState somewhere), react goes through a series of steps in order to update the webpage:
The first group of steps are collectively called the "render phase". In the render phase, react is creating the Virtual DOM. In other words, it's determining what the page is supposed to look like, without actually changing the page. In the simplest form (where we're not skipping any renders with things like react.memo or shouldComponentUpdate), react calls render on the topmost component, and finds out what it returned, and then for each of its children it calls render on those as well until it knows what the whole page should look like.
The second group of steps are called the "commit phase". Now that it knows what the page should look like, it needs to update the actual DOM to match the Virtual DOM. To do this, it compares the current virtual DOM that it got from the render phase with the virtual DOM it got the last time it rendered, and figures out the minimum set of updates in order to make the page look like that.
And now the rendering is done and the page has been updated. During this process it's possible that some components got created for the first time (ie, "mounted"), or they got their props changed (ie, "updated"), or they were removed entirely ("unmounted"). Components that had this happen to them will have their componentDidMount, componentDidUpdate and componentWillUnmount functions called as appropriate.
Render phase: Is used to calculate changes, and may be aborted if the user wants to. If this phase is aborted the DOM isn’t updated.
Pre-commit phase: Is a period where you can read changes made to the VDOM, before they are applied to the actual DOM.
Commit phase: Here the changes are applied and any side effects are triggered.
Mounting: Runs once when the component is created.
Updating: Runs each time a change is made to the component.
Unmounting: Runs once when the component is about to be destroyed.
Have a look at this article for details
https://medium.com/#vmarchesin/the-react-lifecycle-step-by-step-47c0db0bfe73#:~:text=Pre%2Dcommit%20phase%3A%20Is%20a,any%20side%20effects%20are%20triggered.
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.
Is it possible to fire function every time except first one when component has been rendered? If so how could I achieve this?
In fact react has already something for you:
If you look at the docs for componentDidUpdate:
https://facebook.github.io/react/docs/react-component.html#componentdidupdate
componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render.
If you only want to execute on second time and not on third/fourth and so on, simply use some flag to make sure the function is executed only one time (so not on first render, but on second, and not on subsequent renders)
As a side note, an Update occur everytime a props/state change and shouldComponentUpdate return true. This may or may not be what you are looking for.