ReactJS how to fire function on second time component is rendered - reactjs

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.

Related

Why don't redux actions "break" componentDidMount/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.

How to run effect's cleanup of a component BEFORE rendering another one?

Here's a codesandbox as starter. If you click the Toggle button you'll see the following output in the console:
mount secondcomp
unmount firstcomp
How can I make it the other way arround? So cleanup first component before rendering the second. Is this possible at all?
I do understand that effects are always run after render, but this is not what I want in my situation. In my use case I have a common resource (fetch-as-you-render pattern) whose methods are called upon unmount of first component and on render of second.

componentDidMount does show intermediate state even though React docs suggest otherwise

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.

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.

React lifecycle method when component is fully rendered

I need to do some size calculations when a component is fully rendered. The componentDidMount method, however fires as soon as the component is rendered, but it's children are not. This code for example:
componentDidMount(){
console.log(findDOMNode(this).childNodes.length);
}
outputs 0
What is the proper way to trigger some code once a component has been fully rendered, together with any descendant components.
Edit: I don't want to use componentDidUpdate since that method fires on any update. I just need this to be run once.
Edit2: As #NaisheelVerdhan points out, the docs say that componentDidMount ins invoked on children first, but in this case I'm confused as to why my above example returns 0
Typically you want to perform calculations in the render method itself. Is there some reason you cannot do that?
I am sorry everyone.
The component I was rendering initially mounted empty and was filled later. #NaisheelVerdhan was entirely correct.

Resources