Call a child component’s method from its parent in React
Invoking a parent component’s method from a child component is pretty straightforward in React. We can do it by passing the method as a prop to the child component. But what if we want to call a child component’s method from its parent? That is not straightforward, and we will be discussing how we can do this in this article.
Even though this use case is rare, we might need this in some crucial scenarios such as when we need to submit a form in a child component by clicking on a button in the parent component. We will be talking about two different methods that we can use to accomplish this.
Passing the method from the child as an argument into a prop method
The first way of accomplishing this would be to pass the method as an argument into a method passed as a prop from parent to child. I know it sounds complex. Let me break it down for you with an example.
Let’s say we want to print “Hello World” onto the screen from a child component when we click on a button in the parent component. So, our parent component will have a button and the child component.
The child component will have a state and a method to toggle the state. “Hello World” will be printed if the state is set to true and “Goodbye World” otherwise.
Now, the challenge is to call this method that toggles the state, named “toggleHelloWorld”, from the parent component.
Pass a prop method
To begin with, let’s pass a prop method called “toggle” from the parent to the child. This method should accept another method as an argument. So, we can define its type in TypeScript as follows.
The child component should call this prop method by passing the “toggleHelloWorld” method as an argument when the component mounts. Therefore, we need to call the prop method within a “useEffect” hook and pass the prop and the “toggleHelloWorld” method as dependencies. To know why the “toggleHelloWorld” method needs to be passed as a dependency, read this.
Now, since a “useEffect” hook depends on the “toggleHelloWorld” method, every time this method gets initialized, the “useEffect” hook is going to fire. And as every re-render is going to reinitialize this method, the “useEffect” hook is going to fire during every re-render.
Use useCallback
To prevent this, we need to use the “useCallback” hook that initializes a method only when the dependencies passed into the hook change. So, let’s wrap the “toggleHelloWorld” method within the “useCallback” hook and pass the state as a dependency.
Now, every time the state changes, the “useCallback” hook is going to fire, reinitializing the “toggleHelloWorld” method. This in turn is going to trigger the “useEffect” hook. We don’t want this. So, let’s use the functional updater form of “setState” to toggle the state. By using this, we can avoid passing the state as a dependency. This makes sure that the “toggleHelloWorld” method is not reinitialized every time the state changes.
This way we can call the prop method set by the parent when the child component mounts.
Next, we can capture the method passed as the argument into the prop method in the parent component and assign it to a variable. Now, we can call this variable when the button is clicked to invoke the child’s method.
Now, my parent component looks like this.
I can now click on the button in the parent component to make the child component toggle between “Hello World” and “Goodbye World”.
Let’s now move on to the second method.
Calling the method within “useEffect” in the child and firing it by toggling a parent state
I am going to use a similar example to demonstrate this. So, let’s add an additional button to the parent component and an additional state in the child component. This time, we are going to toggle between “Hello Universe” and “Goodbye Universe”. In addition, let’s also create a method to toggle the state called “toggleHelloUniverse”. As before, our goal is to trigger this method from the parent component.
Now, in the parent component, let’s create a state called “trigger” and a method to toggle this state called “hitTrigger”. Let’s pass this “trigger” state as a prop to the child component and call the “hitTrigger” method within the “onClick” handler of the second button. So, whenever we click on this button, the state will be toggled.
Use useEffect
We now need to fire a “useEffect” hook from the child every time the trigger prop changes. So, let’s create a “useEffect” hook and pass the “trigger” prop as a dependency. We can now call the “toggleHelloUniverse” method within this hook. Again, as we saw earlier, we have to pass this method as a dependency into the hook and wrap the method declaration within a “useCallback” hook.
Consequently, every time we click on the button, the parent state is going to get toggled, and that is going to fire this “useEffect” hook, which in turn is going to call the “toggleHelloUniverse” method.
But hold on, there is a rider. The “useEffect” hook is going to be fired on component mount as well. To prevent this let’s use the “useRef” hook. To learn more about this, check out this article.
Now, my parent and child components look like this.
We have now seen two different ways by which we can invoke a child method from its parent component in React. I prefer the former to the latter since we create unnecessary re-renders by toggling a state in the parent component in the latter method.
You can find the full code of the sample app I used here in this repo.
Leave a Reply