Last updated: Apr 7, 2024
Reading timeยท3 min

useImperativeHandleTo call a child's function from a parent component in React:
Child component in a forwardRef.useImperativeHandle hook in the child to add a function to the
Child.childRef.current.childFunction().import {forwardRef, useImperativeHandle, useRef} from 'react'; const Child = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ childFunction1() { console.log('child function 1 called'); }, childFunction2() { console.log('child function 2 called'); }, })); return ( <div> <h2>child content</h2> </div> ); }); export default function Parent() { const childRef = useRef(null); const handleClick = () => { childRef.current.childFunction1(); childRef.current.childFunction2(); }; return ( <div> <Child ref={childRef} /> <h2>parent content</h2> <button onClick={handleClick}>Call child functions</button> </div> ); }

We used a forwardRef to forward
a ref from the Parent component to the Child.
forwardRef method accepts a function that takes the props and a ref as parameters.const Child = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ childFunction1() { console.log('child function 1 called'); }, childFunction2() { console.log('child function 2 called'); }, })); return ( <div> <h2>child content</h2> </div> ); });
The function we pass to forwardRef should return a React node.
We need to forward the ref to the Child so we can use the
useImperativeHandle
hook to customize the Child's instance value that is exposed to the Parent
component when using a ref.
useImperativeHandle(ref, () => ({ childFunction1() { console.log('child function 1 called'); }, childFunction2() { console.log('child function 2 called'); }, }));
The Parent component that renders <Child ref={childRef} /> will be able to
call childFunction1 as childRef.current.childFunction1().
Alternatively, you can use a more indirect approach.
useEffectThis is a three-step process:
count state variable in the Parent component.count variable to the dependencies of the useEffect hook in the
Child.count in the Parent to rerun the child's useEffect.import {useEffect, useState} from 'react'; const Child = ({count}) => { useEffect(() => { const childFunction1 = () => { console.log('child function 1 called'); }; const childFunction2 = () => { console.log('child function 2 called'); }; // ๐๏ธ don't run on the initial render if (count !== 0) { childFunction1(); childFunction2(); } }, [count]); return ( <div> <h2>child content</h2> </div> ); }; export default function Parent() { const [count, setCount] = useState(0); const handleClick = () => { setCount(current => current + 1); }; return ( <div> <Child count={count} /> <h2>parent content</h2> <button onClick={handleClick}>Call child functions</button> </div> ); }

The Parent component declares a count state variable and passes it as a prop
to the Child.
We added the count variable to the dependencies of the
useEffect hook, so every time it
changes, the function we passed to useEffect is going to run.
useEffect(() => { const childFunction1 = () => { console.log('child function 1 called'); }; const childFunction2 = () => { console.log('child function 2 called'); }; // ๐๏ธ don't run on initial render if (count !== 0) { childFunction1(); childFunction2(); } }, [count]);
The Child component declares and calls 2 functions in the useEffect hook.
The Parent can run the logic in the Child's useEffect hook by changing the
count state variable.
count is not equal to 0 before calling the functions in useEffect.if (count !== 0) { childFunction1(); childFunction2(); }
The useEffect hook is run when the component mounts and every time one of its
dependencies changes.
If you don't want to run the logic on mount check that the count variable is
not equal to 0 before calling the functions.
Conversely, if you want to run the Child function from the Parent component when the Child mounts, remove the conditional.
const Child = ({count}) => { useEffect(() => { const childFunction1 = () => { console.log('child function 1 called'); }; const childFunction2 = () => { console.log('child function 2 called'); }; // ๐๏ธ Call function on Mount as well childFunction1(); childFunction2(); }, [count]); return ( <div> <h2>child content</h2> </div> ); };

The code sample calls the Child function from the Parent component when the components mount and every time the button is clicked.
We simply removed the if statement that checks if the count state variable
is equal to 0.