Generally, this is not the way to go about handling things in React. Usually what you want to do is hoist the states and the functions to the parent and pass data down as props (Lifting State Up).
But if you must expose an imperative method on a child component, you can use refs
. Remember this is an escape hatch and usually indicates a better design is available.
The Problem
In this example we will create a simple counter application with the 2 individual counters. It will update the total count value (sum of the 2 counter values) only when the user clicks on the Update Counter
button. To give an illustration, this is what we are going to build.
In case the above link no longer works:
Let's start with creating a basic counter component, which is very simple.
Now, the problem is that we need to get access to the states of the children to sum the value of the counters, which currently are only available in the children.
useImperativeHandle
to the rescue
To achieve what we are building, there are different approaches, but in this case, we will be using useRef
, forwardRef
and useImperativeHandle
.
To begin, we need to pass a ref
from the parent to the children component. So that we can access to the children properties from the outside.
Then, we will create this function in the child component.
Obviously, it's a simple function which returns the current count
state of the component. We will need to access to this function in the parent to get the value it returns. This is where useImperativeHandle
comes to play.
Then in the parent component, we can reach getCount
function appealing to ref.current
That's it, now everytime we click the Update Counter
button, it will update the total count value base on the current count of the 2 counters.
Here is a working CodeSandbox for the example.
To sum it up, we use useRef
which returns a mutable ref
object whose .current
property is initialized to the passed argument. The returned object will persist for the full lifetime of the component. Now, the function getCount
is initialized in .current
property of ref
thanks to the help of useImperativeHandle
. So that the function can be called from the parent component where its ref
has been passed down to the child component by using forwardRef
.