Is there a way to call a child's function from parent in React?

Viewed 8724

I was wondering if it were possible to call a child's function inside the parent?

For example, can I use useRef to create a reference to the child and then call the function like that? Or is there another way?

// Parent
const init = () => {
const childRef = useRef();
childRef.current.child();
}

// Child
const init = () => {
function child() {

}
}
5 Answers

So you need to use useImperativeHandle hook and wrap the child in forwardRef Hoc. useImperativeHandle gives access to functions which are written inside it to the parent component.

  const Child = forwardRef((props,ref)=>{
     useImperativeHandle(ref, () => ({
        test: () => {
           //do something
        }
     }));
    });

in parent

const childRef= useRef();
<Child ref={childRef} />

Execute test function

childRef.current.test();

By using ref you can point it out to a function too,

parent component,

export default function App() {
  const childFnRef = useRef(null);
  const callChildFn = () => {
    if (childFnRef?.current) {
      childFnRef.current("valueOne", "valueTwo", "valueThree");
    }
  }
  return (
    <div>
      <h1>Parent component</h1>
      <ChildComponent ref={childFnRef} />
      <button onClick={callChildFn}>call child fn</button>
    </div>
  );
}

child component

//Ref forwarding is an opt-in feature that lets some components take a ref they receive,
//and pass it further down (in other words, “forward” it) to a child.
const ChildComponent = forwardRef((props, ref) => {
  const childFn = (paramOne, paramTwo, paramThree) => {
    console.log("calling child fn... params are: ", paramOne, paramTwo, paramThree);
  };

  ref.current = childFn;

  return (
    <h2>child component</h2>
  );
})

demo

When you use useRef you must have current after function. Like this

const childRef = useRef();
childRef.current.child();

An example in document: https://reactjs.org/docs/hooks-reference.html#useref

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

Yes, but only if the child component is class component.

Because functional component does not have an instance.

Let's say your child component is a class-based then you just need to have a createRef() inside parent and then pass that to the child.

Then, you can collect that instance from .current property of the ref and then trigger it.

Example,

Parent Component's constructor

this.childRef = React.createRef();

Parent Component's render

 render() {
return <ChildComponent ref={this.childRef} />
}

Child Component

class ChildComponent extends React.Component {
    constructor(props) {
       super(props);
    }

    doSomeThing = () => {}

And then at any event handler, you can execute child function as this.childRef.current.doSomeThing();

Reference: https://reactjs.org/docs/refs-and-the-dom.html#accessing-refs

May be someone looking for functional component. Here is heck without forwardRef and imperative Handler.

In Parent create child Ref like this, const childRef = useRef()

In Child give ref passed from parent => ChildComponent ref={childRef} />

And finally in Parent use like this, childRef.current.goToIndex({index:1)}

Related