How To Call A Child Function From A Parent Component In React?
Sometimes, a developer may need to call a child's function from a parent component. Luckily, React provides simple methods to make this task easy.
To call a child's function from a parent component in React, you can:
- Use a combination of the useImperativeHandle hook with the forwardRef HOC.
- Trigger the function using a useEffect hook inside the child.
This article will analyze both solutions and show how to code them in React.
Let's get to it 😎.
The useImperativeHandle hook
To call a child's function from a parent component, you can use the useImperativeHandle React hook.
The useImperativeHandle hook is a lesser-known hook that customizes the instance value exposed to a parent when using a reference.
Simply put, it modifies a created reference.
Here is the syntax for this hook:
javascriptuseImperativeHandle(ref, createHandle, [deps])
Here are the arguments this hook accepts:
- The ref - The forwarded reference from the parent component.
- The createHandle - A function that returns an object with all the functions you want to expose to the parent.
- The deps - All the dependencies for the createHandle function.
⚠️ It is recommended only to use this hook with the forwardRef higher-order component.
Method #1 - Use the useImperativeHandle hook to call a child function
To call a child's function from a parent, you can use a combination of the useImperativeHandle hook with the forwardRef HOC.
Here is the process to follow:
- Declare the function you want to expose inside the useImperativeHandle hook inside the child.
- Forward the child's reference to the parent.
- Call the function from the parent component.
Here is a code example of this:
1. First, let's define the child component.
javascriptconst Child = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
log() {
console.log("child function");
}
}));
return <h1>Child</h1>;
});
We declare the function we want to expose (in this case, the log function) inside the useImperativeHandle hook.
We also use the forwardRef HOC to get the reference from the parent.
2. Then, let's declare the parent component.
javascriptconst Parent = () => {
const ref = useRef();
return (
<div>
<Child ref={ref} />
<button onClick={() => ref.current.log()}>Click</button>
</div>
);
};
We declare the reference, and we pass it down to the child.
Then, we can use this reference to call the child's function.
And here is the full code:
javascriptimport React, { forwardRef, useImperativeHandle, useRef } from "react";
import { createRoot } from "react-dom/client";
const Child = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
log() {
console.log("child function");
}
}));
return <h1>Child</h1>;
});
const Parent = () => {
const ref = useRef();
return (
<div>
<Child ref={ref} />
<button onClick={() => ref.current.log()}>Click</button>
</div>
);
};
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(<Parent />);
Method #2 - Use the useEffect hook to call a child function
Another simple method to call a child function from a parent component involves using the useEffect hook with a trigger state.
Here is the process to follow:
- We declare a trigger state inside the parent component and pass it down to the child component.
- We listen to changes to this state, and if it changes, we call the exposed function.
- To call the function from the parent, we need to update the trigger state.
Here is a code example:
1. First, let's define the parent.
javascriptconst Parent = () => {
const [trigger, setTrigger] = useState(0);
return (
<>
<button
onClick={() => {
setTrigger((trigger) => trigger + 1);
}}
>
click
</button>
<Child trigger={trigger} />
</>
);
};
We create the trigger state and pass it down to the child component.
We need to increment the trigger state to trigger the child's function.
2. Then, let's define the child component.
javascriptconst Child = ({ trigger }) => {
const log = () => {
console.log("call from parent");
};
useEffect(() => {
if (trigger) {
log();
}
}, [trigger]);
return <h1>Child</h1>;
};
When the trigger state changes, we call the log function.
Since we do not want to call the function when the component mounts, we verify that the trigger state is greater than zero.
And here is the full code:
javascriptimport React, { useState, useEffect } from "react";
import { createRoot } from "react-dom/client";
const Parent = () => {
const [trigger, setTrigger] = useState(0);
return (
<>
<button
onClick={() => {
setTrigger((trigger) => trigger + 1);
}}
>
click
</button>
<Child trigger={trigger} />
</>
);
};
const Child = ({ trigger }) => {
const log = () => {
console.log("call from parent");
};
useEffect(() => {
if (trigger) {
log();
}
}, [trigger]);
return <h1>Child</h1>;
};
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(<Parent />);
Final thoughts
As you can see, calling a child function from a parent component is simple in React.
You have different ways of archiving it:
- You can use the useImperativeHandle hook
- You can use the useEffect hook
If you have a large application, those methods can quickly become unmanageable.
I recommend using a state management library (ex. Zustand) that creates a general store to manage all your application states.
Here are some other React tutorials for you to enjoy: