How To Call A Child Function From A Parent Component In React?

Tim Mouskhelichvili
Tim Mouskhelichvili
4 minutes to read

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 😎.

react call function in child component

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:

  1. Declare the function you want to expose inside the useImperativeHandle hook inside the child.
  2. Forward the child's reference to the parent.
  3. 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:

  1. We declare a trigger state inside the parent component and pass it down to the child component.
  2. We listen to changes to this state, and if it changes, we call the exposed function.
  3. 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.

react call function in child component

Here are some other React tutorials for you to enjoy:

Comments (10)
Reply to:
priyanshu Verma January 26, 2024 13:32PM
how to call a grand child function to a parent component
REPLY
Stefan July 04, 2023 11:48AM
I can't believe this `trigger` `useEffect` shenanigan worked. It bypasses the complicated 3000 `useImperativeAss` hooks, it's brilliant.
REPLY
Leo June 09, 2023 11:00AM
thanks! super useful
REPLY
Favourite Jome May 25, 2023 18:57PM
Thanks for this article
REPLY
SmartCool May 09, 2023 15:42PM
Thanks, it worked!
REPLY
Robe Tobin April 21, 2023 10:25AM
Gold Star. Thank you so much for this. I've come back to this article several times. Could you also outline this in typescript for all my ts devs?
REPLY
nikita April 12, 2023 08:08AM
Hi, I wanted to ask, how do you offer to solve that problem with zustand?
REPLY
Tikto February 22, 2023 02:58AM
Hey, thanks for writing this. This actually solve my problem. I have a question about this part ` setTrigger((trigger) => trigger + 1);` If I do this instead setTrigger(trigger + 1); this isn't work, it only trigger the first instance I click the button. Can you please explain what is actually happening here?
REPLY
Tim Mouskhelichvili February 22, 2023 18:58PM
Yeah, since you are using the previous value of the state you need to use like that: `setTrigger((trigger) => trigger 1);`. Else, it is not going to work.
REPLY
Alan Jereb November 28, 2022 16:55PM
The problem with the second approach is that if the child component rerenders while the parent does not, the useEffect on the child will trigger on rerender, as \"trigger\" is greater than 0.
REPLY