By Evo SL


2016-06-21 16:34:48 8 Comments

I have two components.

  1. Parent component
  2. Child component

I was trying to call child's method from Parent, I tried this way but couldn't get a result

class Parent extends Component {
  render() {
    return (
      <Child>
        <button onClick={Child.getAlert()}>Click</button>
      </Child>
      );
    }
  }

class Child extends Component {
  getAlert() {
    alert('clicked');
  }

  render() {
    return (
      <h1 ref="hello">Hello</h1>
    );
  }
}

Is there a way to call child's method from the parent ?

Note: Child and Parent components are in two different files

7 comments

@rossipedia 2016-06-21 17:34:34

First off, let me express that this is generally not the way to go about things in React land. Usually what you want to do is pass down functionality to children in props, and pass up notifications from children in events.

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.

Previously, refs were only supported for Class-based components. With the advent of React Hooks, that's no longer the case

Using Hooks and Function Components (>= [email protected])

import React, { forwardRef, useRef, useImperativeHandle } from 'react';

// We need to wrap component in `forwardRef` in order to gain
// access to the ref object that is assigned using the `ref` prop.
// This ref is passed as the second parameter to the function component.
const Child = forwardRef((props, ref) => {

  // The component instance will be extended
  // with whatever you return from the callback passed
  // as the second argument
  useImperativeHandle(ref, () => ({

    getAlert() {
      alert("getAlert from Child");
    }

  }));

  return <h1>Hi</h1>;
});

const Parent = () => {
  // In order to gain access to the child component instance,
  // you need to assign it to a `ref`, so we call `useRef()` to get one
  const childRef = useRef();

  return (
    <div>
      <Child ref={childRef} />
      <button onClick={() => childRef.current.getAlert()}>Click</button>
    </div>
  );
};

Functioning example

Documentation for useImperativeHandle() is here:

useImperativeHandle customizes the instance value that is exposed to parent components when using ref.

Using Class Components

class Parent extends Component {
  constructor(props) {
    super(props);
    this.child = React.createRef();
  }

  onClick = () => {
    this.child.current.getAlert();
  };

  render() {
    return (
      <div>
        <Child ref={this.child} />
        <button onClick={this.onClick}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  getAlert() {
    alert('getAlert from Child');
  }

  render() {
    return <h1>Hello</h1>;
  }
}

ReactDOM.render(<Parent />, document.getElementById('root'));

Functioning Example

Legacy API (<= [email protected])

For historical purposes, here's the callback-based style you'd use with React versions before 16.3:

const { Component } = React;
const { render } = ReactDOM;

class Parent extends Component {
  render() {
    return (
      <div>
        <Child ref={instance => { this.child = instance; }} />
        <button onClick={() => { this.child.getAlert(); }}>Click</button>
      </div>
    );
  }
}

class Child extends Component {
  getAlert() {
    alert('clicked');
  }

  render() {
    return (
      <h1>Hello</h1>
    );
  }
}


render(
  <Parent />,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

@Evo SL 2016-06-21 17:58:30

I tired, but end up with this error "_this2.refs.child.getAlert is not a function"

@Evo SL 2016-06-21 18:09:22

and I need to mention that, these components are in two separate files and I am importing the child to the parent

@rossipedia 2016-06-21 18:24:58

In that case, I'd suggest editing your question to reflect that they are in two different files, and posting the exact code that is causing problems.

@Evo SL 2016-06-21 18:33:55

yeh, I modified the question.

@Prabhjot Rai 2016-12-25 15:22:40

This doesn't work when we use react-redux while using mapStateToProps and mapDispatchToProps while exporting the class.

@rossipedia 2016-12-25 19:07:14

That's because connect returns a higher order component that wraps your original instance. You'll need to call getWrappedInstance() on the connected component first to get your original component. Then you can call instance methods on that.

@ffxsam 2017-03-30 16:41:27

This is not really a good pattern. Not to mention string refs are frowned upon. It's better to pass props into the child component and then have a button click in the parent change the parent's state, and pass a state item into the child which will trigger the child's componentWillReceiveProps, and use that as a trigger.

@rossipedia 2017-03-30 17:58:35

No, it's not usually the best pattern, it's more of an escape hatch when you need it, and should be used only in emergencies. Also, this answer was written when string refs were still around, and you're right that they're not the "correct" way of doing things these days.

@technophyle 2017-08-02 21:21:54

@ffxsam there are some cases you can't really do what's best, which you mentioned.

@James Ives 2017-09-04 00:14:34

Question about this, when referencing a child components methods in componentDidMount() is it bad practice to access one which modifies that child components state?

@tatsu 2017-09-06 09:36:51

for those getting _this2.clickChild is not a function this was the correct application of a ref : github.com/kriasoft/react-starter-kit/issues/…

@rossipedia 2017-11-12 22:28:55

@JamesIves sorry for the late response, but as long as that child method is calling setState to alter its own state, then no, there shouldn't be a problem with it.

@aaaaaa 2018-12-03 17:47:39

If best practice is to create a maze of logic to do something as simple as calling a child component's method - then I disagree with best practice.

@Lambert 2019-03-06 21:57:18

This was much easier with classes then with the new hooks function components. I can't believe there is not an easier way than the hooks example above using the "forwardRef". What a mess it makes!

@S.Yadav 2018-11-23 09:42:24

We can use refs in another way as-

We are going to create a Parent element, it will render a <Child/> component. As you can see, the component that will be rendered, you need to add the ref attribute and provide a name for it.
Then, the triggerChildAlert function, located in the parent class will access the refs property of the this context (when the triggerChildAlert function is triggered will access the child reference and it will has all the functions of the child element).

class Parent extends React.Component {
    triggerChildAlert(){
        this.refs.child.callChildMethod();
        // to get child parent returned  value-
        // this.value = this.refs.child.callChildMethod();
        // alert('Returned value- '+this.value);
    }

    render() {
        return (
            <div>
                {/* Note that you need to give a value to the ref parameter, in this case child*/}
                <Child ref="child" />
                <button onClick={this.triggerChildAlert}>Click</button>
            </div>
        );
    }
}  

Now, the child component, as theoretically designed previously, will look like:

class Child extends React.Component {
    callChildMethod() {
        alert('Hello World');
        // to return some value
        // return this.state.someValue;
    }

    render() {
        return (
            <h1>Hello</h1>
        );
    }
}

Here is the source code-
Hope will help you !

@S.Yadav 2019-02-07 06:25:06

Welcome, Happy to hear it worked for you.

@bvdb 2018-11-15 15:02:49

I think that the most basic way to call methods is by setting a request on the child component. Then as soon as the child handles the request, it calls a callback method to reset the request.

The reset mechanism is necessary to be able to send the same request multiple times after each other.

In parent component

In the render method of the parent:

const { request } = this.state;
return (<Child request={request} onRequestHandled={()->resetRequest()}/>);

The parent needs 2 methods, to communicate with its child in 2 directions.

sendRequest() {
  const request = { param: "value" };
  this.setState({ request });
}

resetRequest() {
  const request = null;
  this.setState({ request });
}

In child component

The child updates its internal state, copying the request from the props.

constructor(props) {
  super(props);
  const { request } = props;
  this.state = { request };
}

static getDerivedStateFromProps(props, state) {
  const { request } = props;
  if (request !== state.request ) return { request };
  return null;
}

Then finally it handles the request, and sends the reset to the parent:

componentDidMount() {
  const { request } = this.state;
  // todo handle request.

  const { onRequestHandled } = this.props;
  if (onRequestHandled != null) onRequestHandled();
}

@joeytwiddle 2018-08-20 07:59:22

If you are doing this simply because you want the Child to provide a re-usable trait to its parents, then you might consider doing that using render-props instead.

That technique actually turns the structure upside down. The Child now wraps the parent, so I have renamed it to AlertTrait below. I kept the name Parent for continuity, although it is not really a parent now.

// Use it like this:

  <AlertTrait renderComponent={Parent}/>


class AlertTrait extends Component {
  // You may need to bind this function, if it is stateful
  doAlert() {
    alert('clicked');
  }
  render() {
    return this.props.renderComponent(this.doAlert);
  }
}

class Parent extends Component {
  render() {
    return (
      <button onClick={this.props.doAlert}>Click</button>
    );
  }
}

In this case, the AlertTrait provides one or more traits which it passes down as props to whatever component it was given in its renderComponent prop.

The Parent receives doAlert as a prop, and can call it when needed.

(For clarity, I called the prop renderComponent in the above example. But in the React docs linked above, they just call it render.)

The Trait component can render stuff surrounding the Parent, in its render function, but it does not render anything inside the parent. Actually it could render things inside the Parent, if it passed another prop (e.g. renderChild) to the parent, which the parent could then use during its render method.

This is somewhat different from what the OP asked for, but some people might end up here (like we did) because they wanted to create a reusable trait, and thought that a child component was a good way to do that.

@joeytwiddle 2018-10-22 08:57:26

There is a handy list of patterns for creating re-usable traits here: reactjs.org/blog/2016/07/13/…

@szpada87 2018-08-15 06:46:10

You can make Inheritance Inversion (look it up here: https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e). That way you have access to instance of the component that you would be wrapping (thus you'll be able to access it's functions)

@brickingup 2017-08-09 05:50:03

You can use another pattern here:

class Parent extends Component {
 render() {
  return (
    <div>
      <Child setClick={click => this.clickChild = click}/>
      <button onClick={() => this.clickChild()}>Click</button>
    </div>
  );
 }
}

class Child extends Component {
 constructor(props) {
    super(props);
    this.getAlert = this.getAlert.bind(this);
 }
 componentDidMount() {
    this.props.setClick(this.getAlert);
 }
 getAlert() {
    alert('clicked');
 }
 render() {
  return (
    <h1 ref="hello">Hello</h1>
  );
 }
}

What it does is to set the parent's clickChild method when child is mounted. In this way when you click the button in parent it will call clickChild which calls child's getAlert.

This also works if your child is wrapped with connect() so you don't need the getWrappedInstance() hack.

Note you can't use onClick={this.clickChild} in parent because when parent is rendered child is not mounted so this.clickChild is not assigned yet. Using onClick={() => this.clickChild()} is fine because when you click the button this.clickChild should already be assigned.

@tatsu 2017-09-06 08:54:16

I get _this2.clickChild is not a function why?

@tatsu 2017-09-06 09:36:05

nevermind this worked for me : github.com/kriasoft/react-starter-kit/issues/…

@brickingup 2017-09-06 22:27:11

Did you use onClick={this.clickChild} or onClick={() => this.clickChild()}? The first one won't work coz of the reason in "Note...." part of my answer. The ref approach won't work if you wrap your component in connect() of redux though.

@tatsu 2017-09-07 08:04:59

neither worked. only this answer worked : github.com/kriasoft/react-starter-kit/issues/…

@brickingup 2017-09-07 22:03:20

I have put the code in codepen here: codepen.io/anon/pen/wqLJLq/?editors=1111

@IfTrue 2017-11-19 04:56:09

This worked awesomely - thank you @brickingup. One small change is I had to manually bind the this scope. Applied to your example it would be like the this in the child's componentdidMount: this.props.setClick(this.getAlert.bind(this))

@brickingup 2017-11-26 21:01:43

Hi @ifTrue, yes if you use 'this' in getAlert method you would need to bind it. I didn't use it in my example so I ignored this part.

@joeytwiddle 2018-05-21 05:25:07

This is an interesting technique. It is quite clean and doesn't seem to break any rules. But I do think your answer would be more complete (and meet expectations) if you added a bind. I liked the answer so much I have posted it on this related Github issue.

@Jesus Gomez 2018-09-26 22:24:38

This should be the acepted answer

@Mike Tronic 2016-06-21 18:50:17

https://facebook.github.io/react/tips/expose-component-functions.html for more answers ref here Call methods on React children components

By looking into the refs of the "reason" component, you're breaking encapsulation and making it impossible to refactor that component without carefully examining all the places it's used. Because of this, we strongly recommend treating refs as private to a component, much like state.

In general, data should be passed down the tree via props. There are a few exceptions to this (such as calling .focus() or triggering a one-time animation that doesn't really "change" the state) but any time you're exposing a method called "set", props are usually a better choice. Try to make it so that the inner input component worries about its size and appearance so that none of its ancestors do.

@Jodo 2017-10-11 07:46:38

Here is the source of this answer: discuss.reactjs.org/t/…. No problems with citing others, but at least put in some reference.

Related Questions

Sponsored Content

16 Answered Questions

[SOLVED] Can you force a React component to rerender without calling setState?

  • 2015-06-03 16:44:58
  • Philip Walton
  • 582481 View
  • 487 Score
  • 16 Answer
  • Tags:   reactjs react-jsx

37 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

33 Answered Questions

[SOLVED] How do I return the response from an asynchronous call?

76 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5598524 View
  • 6939 Score
  • 76 Answer
  • Tags:   javascript arrays

8 Answered Questions

[SOLVED] Why do we need middleware for async flow in Redux?

3 Answered Questions

[SOLVED] React js change child component's state from parent component

  • 2016-08-19 14:36:02
  • torayeff
  • 69278 View
  • 62 Score
  • 3 Answer
  • Tags:   javascript reactjs

20 Answered Questions

[SOLVED] What is the difference between call and apply?

1 Answered Questions

[SOLVED] Calling method from parent of every child in <view> array

2 Answered Questions

[SOLVED] Call child component method from parent component in reactjs

  • 2017-06-21 09:26:14
  • Rajan Gupta
  • 4353 View
  • 4 Score
  • 2 Answer
  • Tags:   reactjs

2 Answered Questions

[SOLVED] React - Get the ref present in child component in the parent component

Sponsored Content