I am learning to react lifecycle methods but stuck at a query and not able to find the answer even after lots of research over the web.
As per the react official documentation here, it is said that the method getSnapshotBeforeUpdate is used to perform something just before the DOM commit. The snapshot returned by this function will be later used by componentDidUpdate.
The query:
The parameters 'prevProps' and 'prevState' are already present in method componentDidUpdate, then why does it need the help of function getSnapshotBeforeUpdate? I mean the function componentDidUpdate has necessary inputs to perform what getSnapshotBeforeUpdate is doing.
Any help would be appreciated.
Best,
Rahul
As clearly mentioned in the documentation with an example, the purpose of getSnapshotBeforeUpdate method is not to just get information from prevProps and/or prevState.
But it can be used to extract some information from the previous DOM (such as the current scroll position of a div) before the DOM is updated. Most cases, such DOM related values may not be covered by the prevProps or prevState.
When you consider only the componentDidUpdate method, the DOM has already updated (hence the name DidUpdate) when it's been called. So all the information related to the previous DOM has lost by that time.
Therefore the extracted information on previous DOM from getSnapshotBeforeUpdate can be passed to the componentDidUpdate method to use it there.
Related
Imagine that you've built an application with ReactJs containing a hundred elements. Let's say that in some time, the state of component A changes, and for the sake of simplicity we assume it has only one element and no child component.
My question is: how is Virtual DOM updated in response to the state change?
After a few hours of research, I found two contradictory opinions:
The entire Virtual DOM is torn down; then it is rebuilt from scratch
Only the changed elements are updated in the Virtual DOM.
Unfortunately, official documentation is not clear about this. So, can anybody give the correct answer? (please with supporting reference)
[Edit] : Some parts are imcomplete here, think about reading the comment section !
React update a component when its state or a prop changes. It does a comparison between the previous JSX and the new one and re-render only the differences.
If the parent component has its state or a prop changed, it will be updated.
The child will not be refreshed unless a prop from the parent that is passed to it changes.
Note that the useEffect from the child is triggered first. Knowing that, If you do things that update the state in the child component, then it will be re-rendered everytime (Because the usEffect is triggered everytime if you don't set any dependencies).
Test from Stackblitz - Child Effect is triggered first
Article that made me notice it (I didn't know before this answer :D)
Here is how I understand things in React. To be short, the entire virtual DOM isn't rebuilt from scratch, it's not how JSX comparison works.
I don't have much sources about what I said, but here is the explanation about jsx update from the official documentation. Just that should be enough to eliminate the first point of your list.
I am looking for an explanation of parameters for each component method such as componentDidUpdate(). I see the link https://reactjs.org/docs/react-component.html#componentdidupdate but it does not provide any explanation of the parameters such as prevProps, prevState, and snapshot. Where can I find documentation that describes them?
Is my current understanding of the parameters correct?
prevProps: The props object before render() was called by a change in either state or props.
prevState: The state object before render() was called by a change in either state or props.
snapshot: ???
prevState and prevProps are the state and props from the previous render cycle, as opposed to this.state and this.props from the current render cycle.
The snapshot comes from getSnapshotBeforeUpdate
Any value returned by this lifecycle will be passed as a parameter to
componentDidUpdate().
You can find the react component documentation here.
Aside from the documentation there are a few good blog posts on the web explaining the various lifecycle methods, when to use them and how they work:
https://blog.logrocket.com/the-new-react-lifecycle-methods-in-plain-approachable-language-61a2105859f3/
https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1?gi=3ac3c7c8ff34
A far as I know there is no other, more specific documentation about lifeCycleMethods.
Parameters such as prevProps and prevState are pretty much self-explanatory. Even if someone isn't sure what they are, console.log(prevProps, prevState) could help. My assumption is that self-explanatory nature of these parameters is what makes them ommited from detailed explanation in docs.
On the other hand, snapshop which is not that much self-explanatory is explained:
If your component implements the getSnapshotBeforeUpdate() lifecycle (which is rare), the value it returns will be passed as a third “snapshot” parameter to componentDidUpdate(). Otherwise this parameter will be undefined.
I don't see anything in the docs specifically about SS, I know P=props, and S=state but SS?
edit
Sorry, I was referencing this from a React+TypeScript project, namely #types/react. I have added the typescript tag.
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L395
It's used in the return value of getSnapshotBeforeUpdate so I'm betting it stands for SnapShot.
Runs before React applies the result of render to the document, and
returns an object to be given to componentDidUpdate. Useful for saving
things such as scroll position before render causes changes to it.
And the docs in that file for componentDidUpdate show it accepts a third argument called snapshot that says:
The snapshot is only present if getSnapshotBeforeUpdate is present and returns non-null.
So, SS is the user defined type of the snapshot returned by your custom implementation of getSnapshotBeforeUpdate, which gets passed to componentDidUpdate so you can preserve some application specific details from the last render.
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.
I've read the ReactJS documentation about setState. Specifically, this line:
NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.
But in my code, I do things like this:
var x = this.state.x;
x.y.z.push("foo"); // z is a list
this.setState({x:x});
This code seems to work and update state correctly. But according to the documentation, I'm breaking the rules. What's the problem with this approach? Are there performance issues? Race conditions? Will I be scolded by the Facebook dev team? Ideally, I'd like to avoid the immutability helpers and all the other craziness and keep things simple.
By manipulating state directly, you are circumventing React's state management, which really works against the React paradigm. The most significant benefit of React's setState is that it immediately triggers a re-render, which merges your DOM changes from the shadow DOM into the document DOM. So, you capture all the state changes you need in some handler, then build up the state changes you want in a literal object, then pass that to setState. This is not quite what your example above does.
So while the code sample you provided technically breaks this rule, since you are calling setState directly after mutating through a reference to a state object property, your changes are immediately being funneled through React's state management. So, everything will work as you expect. The idea is that you don't want to get in the habit of making many changes to state in this way, it's better to capture your intended state in a new literal object or array, then set it to the state once (i.e., with no previous mutations of state) through a call to setState, which will trigger a single re-render.
EDIT: To more definitively answer your question, I would add that the real concern is that a dev would directly manipulate state in many different places or methods, without calling setState, and then at some later point or other code, call setState and then wonder why their render isn't producing the results they expected. Since setState does an object merge between the known, managed state, and the literal object passed as an argument to setState, it's possible the results would not be what you would expect if you had previously manipulated state directly.
The reason is that you miss out on the callbacks associated with this.setState and they claim that you may overwrite data by just assigning straight to the object.
Also, often in OOP (I don't know how many stars JS gets...) you'll use getter and setter methods instead of directly manipulating the object. In this example via this.state.prop1 = "xyz";
I've never had react overwrite my directly set state properties. The temptation to code it this way may be write to state without re-rendering. But if you're doing that you may think about not putting those in state anyways.
If re-rendering performance is an issues checkout https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate
The main reason is that shouldComponentUpdate will not work correctly.