React - How do I access a function in another component?

cbll picture cbll · Apr 27, 2017 · Viewed 10.7k times · Source

My structure is as such:

       <ParentComponent />
 <Child 1 />     <Child 2 />

I have a function in <Child 1 />. Since <Child 1 /> controls the grid-layout, and <Child 2 /> is a Navbar with buttons, I want to have a button in <Child 2 /> which will reset some parameters in <Child 1 />.

How do I achieve this? As far as I can see, refs will only be able to go one "step" up the tree, not down.

There isn't any obvious way this function can be invoked from the parent component. Is there any way here? All the solutions I can think of aren't really following the React-mindset, namely the unidirectional data-flow.

Answer

Mamdouh Alsarayreh picture Mamdouh Alsarayreh · Apr 27, 2017

You can make the parent component as a container for both components. So all the states and functions are handled in the parent components and pass them to the other components as props.

e.g.

    class Parent extends React.Component {

         constructor() {
             super();
             this.state = {
                 controls: controls
             }
         }

         onClick = (dataFromChild2) => {
              //Resetting
              this.setState({controls: dataFromChild2})
         }

         render() {
             return (
                 <div>
                      <Child1 gridControl={this.state.controls}/>
                      <Child2 onClick={this.onClick}/>
                 </div>
             )
         }
    }

You can access the gridControl and onClick from this.props in the children components

UPDATE

Think of it this way, you have the Parent component with the states and function needed to handle the data. The children components take those data and update their states accordingly.

Let's Say the Parent Component is something like this:

class Parent extends React.Component {

  constructor() {
    super();
    this.state = {
      gridControl: {}
    }
  }

  onChild2ButtonClick = (dataFromChild2) => {
    this.setState({
      gridControl: dataFromChild2
    });
  };

  render() {
    return (
      <div>
        <Child1 controls={this.state.gridControl}/>
        <Child2 onClick={this.onChild2ButtonClick}/>
      </div>
    );
  }
}

Child2 Component is something like this:

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

  onClick = () => {
    var data = {};
    this.props.onClick(data);
  };

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

If you're using states for Child1, and don't want to change them to props with function in the Parent component to handle them, then you update the state in the componentWillReceivePropsmethod with the new props received from the parent component, so that the props sent will match the states used in Child1 component.

Hope this will clear things up.