Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React access siblings component methods

Tags:

reactjs

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() {...}

}
like image 971
Kup Avatar asked Mar 08 '23 12:03

Kup


2 Answers

You can't do this, you're going against the React design purposes which help ensure components are well designed and not tightly coupled to others.

You'll need to define the methods on the parent and pass these into the child components as properties if you want have methods to be shared between multiple different components.

The life cycle hooks will still have access to the component properties if you need to call a method within one of these.

like image 77
Martin Campbell Avatar answered Mar 15 '23 04:03

Martin Campbell


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).
like image 32
cbdeveloper Avatar answered Mar 15 '23 05:03

cbdeveloper