React access siblings component methods

Viewed 3112

Using React [15.6.1] Redux [3.7.2] and Router [4.1.1] I'm tryin to access a method that belongs to other (siblings) components but can't seem to be able to access them. Is there anyway to export those methods?

               ----------
               ¦ Parent ¦
               ----------
                   ¦
    -------------------------------
    ¦              ¦              ¦
-----------    -----------    -----------
¦ Child 1 ¦    ¦ Child 2 ¦    ¦ Child 3 ¦
-----------    -----------    -----------


// Child 1 has a method submitChild1()
// Child 2 has a method submitChild2()
// Child 3 has to access both of those methods


class Parent1 extends React.Component {

    render() {
        return (
            <div>
                <Child1 />
                <Child2 />
                <Child3 />
            </div>
        );
    }

}

class Child1 extends React.Component {

    submitChild1() {
        dispatch(Action1());
    }

    render() {...}

}

class Child2 extends React.Component {

    submitChild2() {
        dispatch(Action2());
    }

    render() {...}

}

class Child3 extends React.Component {

    submitTheOtherMethods() {
        // try to access Child 1 method
        // try to access Child 2 method
    }

    render() {...}

}
2 Answers

You can achieve this behavior. Of course, the information will have to be passed around through a common ancestor (parent) of the sibling. You can do that using the useRef hook, for example:

function App() {
  
  const child1Method_ref = React.useRef(null);
  
  return(
    <React.Fragment>
      <Child1
        child1Method_ref={child1Method_ref}
      />
      <Child2
        child1Method_ref={child1Method_ref}
      />
    </React.Fragment>
  );
}

function Child1(props) {

  const child1Method = React.useCallback(()=>{
    console.log('I am a Child 1 method!!!');
  },[]);
  
  React.useEffect(()=>{
    props.child1Method_ref.current = child1Method
  },[]);
  
  return(
    <div>I am Child 1 (I declared the method)</div>
  );

}

function Child2(props) {
  return(
    <React.Fragment>
      <div>I am Child 2</div>
      <button onClick={()=>props.child1Method_ref.current()}>
        Click to call Child 1 method from Child 2
      </button>
    </React.Fragment>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

Here is how it works:

  • The useRef points to an object, which the reference will be preserved across renders. I.e: the object will not change. The very same object will be accessible throughout the full lifecycle of the components.
  • That object child1Method_ref is passed down to Child1 and it runs a useEffect to update it and stores the method inside the current property of the object. Obs: The useRef object actually has a property named "current".
  • Child2 also receive the same object through props and can access the method from Child1 that has been stored into the ref object.
  • The useCallback is used to keep the same reference for the function across renders. I.e: the function remains the same in this case (it's not recreated on every render).
Related