Calling Child’s function from Parent with react hooks

There are many scenarios that we want to call child’s function from it’s parent. This can be done easily with forwardRef and useImperativeHandle.

Let’s define our scenario.
We have a dialog component that could be open by clicking a button, this button is in the parent component.
This is the parent component:

const App = () => {
const [open, setOpen] = useState(false);
return (
<>
<Button
onClick={() => setOpen(true)}
>
Open Dialog
</Button>
<CustomDialog
open={open}
onClose={() => setOpen(false)}
name="React"
/>
</>
);
};

In this code we have open state that controls state of the dialog (show or hide).
Let’s see code:

const CustomDialog = ({ open, name, onClose }) => {
const closeHandler = () => {
onClose();
};
return (
<Dialog onClose={closeHandler} open={open}>
<DialogTitle>Hello {name}</DialogTitle>
</Dialog>
);
};

We define and in props, so it could be controlled from the parent component.

Now, we change component to control state of dialog inside component not from it’s parent:

const CustomDialog = ({ name }) => {
const [open, setOpen] = useState(false);
const closeHandler = () => {
setOpen(false);
};
const openHandler = () => {
setOpen(true);
};
return (
<Dialog onClose={closeHandler} open={open}>
<DialogTitle>Hello {name}</DialogTitle>
</Dialog>
);
};

So, we have to call function from parent to open the dialog.
So, this is what we want to learn now, call Child’s function from its’s parent.
To achieve this we use forwardRef and useImperativeHandle

With we can get the that passed to component.

We need the to use in useImperativeHandle.

With useImperativeHandle we can customizes the instance value that is exposed to parent components when using .

In the code below, uses to obtain the passed to it. Also the parent component that renders would be able to call .
So, each function that we want to call it from the parent component, should be defined in useImperativeHandle.

const CustomDialog = forwardRef((props, ref) => {
const [open, setOpen] = useState(false);
const closeHandler = () => {
setOpen(false);
};
const openHandler = () => {
setOpen(true);
};
useImperativeHandle(ref, () => ({
openDialog() {
openHandler();
}
}));
return (
<Dialog onClose={closeHandler} open={open}>
<DialogTitle>Hello {props.name}</DialogTitle>
</Dialog>
);
});

We change the parent component to be like this, We create a new with and pass to and we can call on onClick with .

const App = () => {
const classes = useStyles();
const dialogRef = createRef();
return (
<div className={classes.app}>
<Button
variant="contained"
color="primary"
disableElevation
onClick={() => dialogRef?.current?.openDialog()}
>
Open Dialog
</Button>
<CustomDialog ref={dialogRef} name="React" />
</div>
);
};

So, now when click the button, our will be opened.

This approach is very useful to decrease parent component rendering, But you should use useImperativeHandle when it is necessary.

As always, imperative code using refs should be avoided in most cases.

Bonus: Adding types

Now we show how to make some changes to add types with typescript.
We add types for and .

export interface CustomDialogProps {
name: string;
}
export interface CustomDialogRef {
openDialog: () => void;
}

and change component to this:

export interface CustomDialogProps {
name: string;
}
export interface CustomDialogRef {
openDialog: () => void;
}
const CustomDialog = forwardRef<CustomDialogRef, CustomDialogProps>(
(props, ref) => {
const [open, setOpen] = useState(false);
const closeHandler = () => {
setOpen(false);
};
const openHandler = () => {
setOpen(true);
};
useImperativeHandle(ref, () => ({
openDialog() {
openHandler();
}
}));
return (
<Dialog onClose={closeHandler} open={open}>
<DialogTitle>Hello {props.name}</DialogTitle>
</Dialog>
);
}
);

We can create a and set it’s type like this:

const dialogRef = createRef<CustomDialogRef>();

now we can use power of typescript and IDE intelligence while coding.

I’m good with JS

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store