When you need to call a function declared in the parent component from a child component, it is as easy as passing it as a prop to the child component and calling it from the child component. However, when you want to call the other way around, things can be a bit tricky. In this article, we will see how to the call child component function from the parent component.
Consider the following example:
1const ChildComp = () => {2 function showAlert() {3 alert("Hello from Child Component")4 }5 return <div></div>6}78function App() {9 return (10 <div>11 <button>Click Me</button>12 <ChildComp />13 </div>14 )15}1617export default App
Here we have a parent component with a button and a child component with a function to show an alert.
If you want to call the showAlert
function when the button is clicked, there is no direct way to access it.
Let's add a reference to the child component in the parent component using useRef
hook.
1import { useRef } from "react"23const ChildComp = () => {4 function showAlert() {5 alert("Hello from Child Component")6 }7 return <div></div>8}910function App() {11 const childCompRef = useRef()12 return (13 <div>14 <button>Click Me</button>15 <ChildComp ref={childCompRef} />16 </div>17 )18}1920export default App
Now if you run the application and see, you will get the following warning in the console:
Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
How to fix this? As the warning itself suggests, we need to use forwardRef
to enclose the child component.
1import { forwardRef, useRef } from "react"23const ChildComp = forwardRef((props, ref) => {4 function showAlert() {5 alert("Hello from Child Component")6 }7 return <div></div>8})910function App() {11 const childCompRef = useRef()12 return (13 <div>14 <button>Click Me</button>15 <ChildComp ref={childCompRef} />16 </div>17 )18}1920export default App
When we enclose the child component with forwardRef
,
it receives a second parameter apart from props, which is the ref passed from the parent component.
Now with the help of this ref, we can specify which functions can be accessed by the parent component.
This can be done using useImperativeHandle
hook, as shown below:
1import { forwardRef, useRef, useImperativeHandle } from "react"23const ChildComp = forwardRef((props, ref) => {4 useImperativeHandle(ref, () => ({5 showAlert() {6 alert("Hello from Child Component")7 },8 }))9 return <div></div>10})1112function App() {13 const childCompRef = useRef()14 return (15 <div>16 <button>Click Me</button>17 <ChildComp ref={childCompRef} />18 </div>19 )20}2122export default App
useImperativeHandle
hook accepts 2 mandatory parameters,
the first is the reference and the second is the initialization function, to which we can pass our showAlert
declaration.
Finally, let's bind the click event of the button with the showAlert
function:
1import { forwardRef, useRef, useImperativeHandle } from "react"23const ChildComp = forwardRef((props, ref) => {4 useImperativeHandle(ref, () => ({5 showAlert() {6 alert("Hello from Child Component")7 },8 }))9 return <div></div>10})1112function App() {13 const childCompRef = useRef()14 return (15 <div>16 <button onClick={() => childCompRef.current.showAlert()}>Click Me</button>17 <ChildComp ref={childCompRef} />18 </div>19 )20}2122export default App
Now if you run the application and click on the button, you should be able to see the alert:
You can view the source code here.
Do follow me on twitter where I post developer insights more often!