From the changelog for React v0.13:
"ref resolution order has changed slightly such that a ref to a component is available immediately after its componentDidMount method is called; this change should be observable only if your component calls a parent component's callback within your componentDidMount, which is an anti-pattern and should be avoided regardless"
So, is there a better way to access this.refs after the DOM mounts? I dislike using setTimeout(), but that is the best method I see to work on a specific DOM after it mounts. Is there a replacement method I am missing? Or, is the best way to attach an onLoad method directly to the component?
Maybe you are reading too much into this.
My interpretation is that all refs to child components are available in componentDidMount.
The change is that they are not available before the child component's own componentDidMount has completed (which happens before the parent component's). And you would only be affected by that if you call some callback from inside componentDidMount of the child, and that code tries to use the ref immediately. Which seems like an edge-case and, as they say, an anti-pattern.
So "normal usage" should not be impacted by this change.
Please try and report back.
Related
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 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 need to execute a piece of code after all grandchildren of a Component are rendered to scroll to one of the grandchildren. The structure looks like this:
`<GrandParent>
<IntermediateParent>
<IntermediateParent2>
<GrandChild/>
<GrandChild/>
<GrandChild/>
<GrandChild/>
</IntermediateParent2>
</IntermediateParent>
</GrandParent>`
The render method of GrandParent looks like this:
render() {
if (!this.props.listOfGrandchildren) { // still loading data from server
return <div>LOADING...</div>
}
return <IntermediateParent grandchildren={this.props.listOfGrandchildren} />
}
It is clear that using ComponentDidMount will clearly not work because of the children being mounted at a later time, after the data is loaded from the server. In this case, CDM of GrandParent would be triggered before CDM of any GrandChild
I could pass down a method from top to each GrandChild that would be called at CDM. On GrandParent I would wait for all GrandChild to call that method by using a counter and once the counter would be equal to the number of grandchildren I could call my piece of code that would scroll to the wanted grandchild, but this feels like a lot of hassle.
I want to load the GrandParent before the data comes down from the server, to render a placeholder/loading element.
I am looking for a more elegant method to solve this.
UPDATE:
Is componentDidMount of parent called after all componentDidMount of children?
I know why my GrandChildren's CDM is triggered after CDM of GrandParent just looking to have a different behaviour
In the end the most neat solution was the following:
I set up ComponentDidMount on IntermediateParent (works with IntermediateParent2 as well) which calls an action creator that sets a flag loadedX = true.
Then, in GrandParent's ComponentWillReceiveProps wait for the loadedX prop to become true. When this happens, manually call the desired 'callback' function. I inject the loadedX prop to GrandParent using connect.
Hope this also helps someone else. If you need more details ask in comments. I can also come up with some code for a more real world example.
We know that the children will render() when the parent render()s. This means we need to hook onto a parent render() and see if the children exist yet. We don't want to hook onto a child render() because that will run too many times and is kind of out of the scope of the child.
Looking at the React Component Lifecycle, we see that there are two ways to hook on after a parent render(), componentDidMount() and componentDidUpdate(). We know that we can't use componentDidMount() because the parent mounts before the children. However, we can use componentDidUpdate(). In your componentDidUpdate(), you can use refs, document.querySelector(), document.getElementById(), etc. to get a reference to the child. Once you are able to get the child reference, set a boolean flag so you only run the callback inside componentDidUpdate() once.
I feel like this is a cleaner solution. I think the accepted answer is kind of roundabout. You modify the IntermediateParent with ComponentDidMount(), actions using a dispatched redux action or a callback function in parent, and then the componentWillReceiveProps(). The componentWillReceiveProps() will also require a boolean flag like my solution.
Actually, maybe it isn't out of the scope of the child. Another solution is for the parent to pass a callback down to the child to call during the child's componentDidMount(). This callback will be called each time a child mounts, but you can keep a boolean flag in the parent so that the code only runs once.
As far as I can tell, if I pass a parent component state down to a child, then that child gets the live state of the parent.
So a change made in the state of the parent is immediately also available in the child via the prop that it came on.
Is this correct?
It's basically the same mechanism as anywhere else in the language, as you'd expect. Primitives are passed by value and variables that aren't primitives will be passed by reference.
React takes care internally of the updating of props, so that children always have the most up-to-date value of the prop.
This is the lifecycle method that is called when receiving new values for props.
However, make sure you respect the infrastructure put in place and the exposed API that React gives you.
Short answer: props are passed by reference.
The reason it can be confusing: if you change the parent's state by hand (bad practice!), the object will change in the child component, too. But won't trigger re-render! (The child component won't "know" that its props has changed.) So you won't see the UI change.
However if you change the parent's state with setState (the preferred practice), the child will be notified, that it must re-render itself.
If you pass down the state of the component as props to its child, then if the state of the parent component changes it re-renders, which will also re-render its children with the refreshed properties. The children don't directly listen for the state change like the parent does, they are simply re-rendered as as result of its parents state change and updated.
Take a look at this - https://facebook.github.io/react/docs/multiple-components.html. It will help you get your head round how this concept works. Hope this helps!
When the state of a component is changed, then the component is re-rendered by React. While doing that , its child components are also re-rendered, which causes changes in them also.
No, they will not be duplicated, you will access to those props by reference, because they come from a single object wich defines them, and then pass them as a reference to the child objects.
You can take a look to the official documentation here: https://reactjs.org/docs/react-component.html.
I suggest to use a stateless mechanism to handle large data, expecially if shared.
Personally I use mobx (https://github.com/mobxjs/mobx) wich is a great framework to create stateless apps.
With this method you can handle data and state updates in a single component, called Store, and use components to render html only, and not to handle data, wich is a great boost on application performances.
Is there any difference between those 2 functions? (besides their arguments)
It seems like those methods have the same triggers, isn't it?
Appreciate your help :)
componentDidUpdate is called whenever the component has re-rendered, which might be caused by either:
a change in state
a call to forceUpdate
a parent component re-rendering (or another call to React.render in the case of the top-level component)
The setState callback will only be called once the state transition has completed and the component has re-rendered.
The difference is the usage of those two: componentDidUpdate() needs to be declared only once per component, while the callback argument of setState() needs to be passed in every place the setState() method is called.
It's like putting all your eggs in one basket: you don't need to carry around different bags, however if you might want to boil some of the eggs and some to make an omelette from, and in this case you use multiple bags.