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.
Related
Is something like method working like ComponentDidMount, but is calling just in the first mounting not for every?
No, there is not function like this. However, you can keep track of how many times a component mounts in its parent state and with a callback function. Alternatively, the parent can send a flag that indicates what the child should render.
I have 2 stateful class-based components nested within my main app, a parent class-based component. From child component 1, I've successfully called a parent callback method. From within that parent callback I want to call a method of child component 2, so I can setState of #2 without re-rendering the parent component. I've seen that many devs make the children stateless or even just omit them. However, React encourages devs to "componenatize" ... pointers plz!
if that's the case then you shoud consider lifting the state up to the parent: https://reactjs.org/docs/lifting-state-up.html
your child component should only then call parent methods to update the state, that way, you will have a unidirectional flow of data as what a react app should be. Basically, it encourages you to have a single source of truth and ensure synchronisation of data across your app. Besides it removes unnecessary logic like what you are doing right now:
What does the "single source of truth" mean?
Storing the data in the parent's state and then allowing both children to update it via setStates wouldn't violate the concept of "componentizing" as long as the two children have narrowly declared inputs. If one child needs to update data inside another child, you can jump up a context level and store it in the parent- then an update of the data from either child will trigger a render of both children ensuring the display stays synchronized with the data while keeping the data in a single place (with the parent instead of split between the children).
Bingo, yes I can use a "React ref" to call an instance method of a child component. A ref is an attribute on a component instance. So, right now my child component uses its componentDidUpdate to call a callback in my parent, and the parent callback then uses refs to call an "update" method of specific child components. These update methods setState on child component and voila.
So a colleague explained that calling setState in my main app actually will call setState on all children components (related by JSX expressions). Even though I liked the idea of nesting my event handlers within their relevant child components, it seems that the best practice pattern is to have all handlers in the main app, setState in the main app, then let React do its thing
Have searched for a solution to this [seemingly] simple problem, but being relatively new to Node, haven't quite figured it out.
I need to set a prop on an imported Component prior to it rendering. The value for the prop is dynamic and based on the response of an API.
Based on what I've read, this should occur in the Constructor of my umbrella "App", but have few issues:
1) the Component throws an error when the prop value is set by API
2) I think this is because React attempts to render the Component before the API call completes
The Component renders without error if I manually set a valid value.
So, wondering how to grab the value and set the prop before the Component renders to avoid the error.
I can post a code sample, but have tried so many variations I'm not sure they'd be that useful.
Let me know if I am misunderstanding this.
You have two components, Component Parent and Component Child.
Component Parent gets information from an API, and sends it to Component Child.
Component Child renders depending on what you Parent sends to it
So, I believe the problem is that Child is not waiting for the API call to finish to render.
If I make an API call, I am not going to have the information for it immediately. You might want to handle the case where Child does not have the prop. To do that, you can call Child like this:
class Parent extends React.Component {
// Make the request to the API and handle the response
render(){
//Set the result of the API call to state.itemFromApiCall
return <div><Child item={this.state.itemFromApiCall} /></div>
}
}
And your Child component would look like this:
function Child (props){
if(!props.item)
return <span>Loading...</span>
//Then you have your component as you had before
}
On first Render, Child will not crash because it knows that prop.item might be undefined. Whenever you actually get the value of the API call, Child will behave as expected.
Hope it helps!
I need to reset a child component from parent. I know the best way is to send a props. So I send reset = true as properties. But looks like I need to have a callback function to parent from the child to change that properties to false after reset is done, so if it happens again, the rest works.
I do not want to use refs as it is not the best method, but I do not want to have callbacks too.
What other suggestion you would have?
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.