How to access component methods from “outside” in ReactJS?

JavascriptReactjsDom

Javascript Problem Overview


Why can’t I access the component methods from “outside” in ReactJS? Why is it not possible and is there any way to solve it?

Consider the code:

var Parent = React.createClass({
	render: function() {
		var child = <Child />;
		return (
			<div>
				{child.someMethod()} // expect "bar", got a "not a function" error.
			</div>
		);
	}
});

var Child = React.createClass({
	render: function() {
		return (
			<div>
				foo
			</div>
		);
	},
	someMethod: function() {
		return 'bar';
	}
});

React.renderComponent(<Parent />, document.body);

Javascript Solutions


Solution 1 - Javascript

React provides an interface for what you are trying to do via the ref attribute. Assign a component a ref, and its current attribute will be your custom component:

class Parent extends React.Class {
    constructor(props) {
        this._child = React.createRef();
    }

    componentDidMount() {
        console.log(this._child.current.someMethod()); // Prints 'bar'
    }

    render() {
        return (
            <div>
                <Child ref={this._child} />
            </div>
        );
    }
}

Note: This will only work if the child component is declared as a class, as per documentation found here: https://facebook.github.io/react/docs/refs-and-the-dom.html#adding-a-ref-to-a-class-component

Update 2019-04-01: Changed example to use a class and createRef per latest React docs.

Update 2016-09-19: Changed example to use ref callback per guidance from the ref String attribute docs.

Solution 2 - Javascript

If you want to call functions on components from outside React, you can call them on the return value of renderComponent:

var Child = React.createClass({…});
var myChild = React.renderComponent(Child);
myChild.someMethod();

The only way to get a handle to a React Component instance outside of React is by storing the return value of React.renderComponent. Source.

Solution 3 - Javascript

Alternatively, if the method on Child is truly static (not a product of current props, state) you can define it on statics and then access it as you would a static class method. For example:

var Child = React.createClass({
  statics: {
    someMethod: function() {
      return 'bar';
    }
  },
  // ...
});

console.log(Child.someMethod()) // bar

Solution 4 - Javascript

As of React 16.3 React.createRef can be used, (use ref.current to access)

var ref = React.createRef()

var parent = (
  <div>
    <Child ref={ref} />
    <button onClick={e=>console.log(ref.current)}
  </div>
);

React.renderComponent(parent, document.body)

Solution 5 - Javascript

Since React 0.12 the API is slightly changed. The valid code to initialize myChild would be the following:

var Child = React.createClass({…});
var myChild = React.render(React.createElement(Child, {}), mountNode);
myChild.someMethod();

Solution 6 - Javascript

You could also do it like this, not sure if it's a good plan :D

class Parent extends Component {
  handleClick() {
    if (this._getAlert !== null) {
      this._getAlert()
    }
  }
  
  render() {
    return (
      <div>
        <Child>
        {(getAlert, childScope) => (
          <span> {!this._getAlert ? this._getAlert = getAlert.bind(childScope) : null}</span>
        )}
        </Child>
        <button onClick={() => this.handleClick()}> Click me</button>
      </div>
      );
    }
  }

class Child extends Component {
  constructor() {
    super();
    this.state = { count: 0 }
  }

  getAlert() {
    alert(`Child function called state: ${this.state.count}`);
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return this.props.children(this.getAlert, this)
  }
}

Solution 7 - Javascript

As mentioned in some of the comments, ReactDOM.render no longer returns the component instance. You can pass a ref callback in when rendering the root of the component to get the instance, like so:

// React code (jsx)
function MyWidget(el, refCb) {
    ReactDOM.render(<MyComponent ref={refCb} />, el);
}
export default MyWidget;

and:

// vanilla javascript code
var global_widget_instance;

MyApp.MyWidget(document.getElementById('my_container'), function(widget) {
    global_widget_instance = widget;
});

global_widget_instance.myCoolMethod();

Solution 8 - Javascript

Another way so easy:

function outside:

function funx(functionEvents, params) {
  console.log("events of funx function: ", functionEvents);
  console.log("this of component: ", this);
  console.log("params: ", params);
  thisFunction.persist();
}

Bind it:

constructor(props) {
   super(props);
    this.state = {};
    this.funxBinded = funx.bind(this);
  }
}

Please see complete tutorial here: How to use "this" of a React Component from outside?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1518183View Question on Stackoverflow
Solution 1 - JavascriptRoss AllenView Answer on Stackoverflow
Solution 2 - JavascriptSjoerdView Answer on Stackoverflow
Solution 3 - JavascriptPaul O'ShannessyView Answer on Stackoverflow
Solution 4 - JavascriptJayView Answer on Stackoverflow
Solution 5 - JavascriptYevgen SafronovView Answer on Stackoverflow
Solution 6 - JavascriptswennemenView Answer on Stackoverflow
Solution 7 - JavascriptmgalgsView Answer on Stackoverflow
Solution 8 - JavascriptHou SouneView Answer on Stackoverflow