Tomas
Tomas

Reputation: 3204

How do you do this in ReactJS?

First off, I'm new to ReactJS. I've done a lot of searching, but I can't find an answer to this question. Maybe it's simple...

I'm needing to communicate between independent components in ReactJS. Imagine my app does not have control over a 'parent' component in the web page it is called on and the app has something like:

class Widget1 extends React.Component {
  render(){
    return <button>Update Widget 2</button>
  }
}

class Widget2 extends React.Component {
  render(){
    return <textarea></textarea>
  }
}

ReactDOM.render(<Wiget1 />, document.getElementById('widget1'));
ReactDOM.render(<Widget2 />, document.getElementById('widget2'));

And the HTML looks like:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Setup</title>
    </head>
    <body>
        ...SOME OTHER HTML
        <div id="widget1"></div>
        ...SOME OTHER HTML
        <div id="widget2"></div>
        ...SOME OTHER HTML
    </body>
</html>

Is it possible to have these components talk to each other when there is no shared parent?

For instance just passing a value from the button in Widget 1 to the Widget 2 textarea. Obviously that's not at all what I'm doing in the end, but it's in that direction.

Thanks.

Upvotes: 1

Views: 115

Answers (2)

Alexey Sidash
Alexey Sidash

Reputation: 441

Sure, your components should communicate somehow.

Parent -> Child communicaton is done with props. Child behaves according to propeties given from parent.

Child -> Parent communication is done with(surprize!) properties.

For example:

//Parent's render method
return (
    <div>
      <Child someEventHandler={(e)=>{console.log('Some event happened!')}}
    </div>);
// ...
// Child render method
return (
    <div>
      <button onClick={(e)=>{if(typeof this.props.someEventHandler === 'function'){this.props.someEventHandler()}}}>
          I trigger some event!
      </button>
    </div>
);

Your child component knows how handle some event(Click, DoubleClick, etc...) and trigger some handler taken from parent with props. This concept allows us reuse low-level(aka dumb) components. For example, you can implement something like <SearchField onSubmit={...} onReset={...} /> component and render it in different places of your application, but pass different onReset and onSubmit callbacks.

Also, your components can communicate with refs. For example:

// Parent's render method
return (
  <div>
    <Child1 onSomeEvent={(e)=>{this.refs.child2.someMethod(e)}}
    <Child2 ref="child2"/>
  </div>
);

When you do something like <Child2 ref="child2"/> In some parent component, reference to instance of Child2 is put into Parent.refs.child2 and you can directly call "public" methods of Child1.

React is awesome! Good luck!

Sinclerely,

Alexey

Upvotes: 0

Naisheel Verdhan
Naisheel Verdhan

Reputation: 5133

If data can flow from <Widget1/> to <Widget2/>, then they are not completely independent and can be children of one <ParentComponent/>.

However, if you still wish to communicate while keeping these <Widget/> s independent, this can be achieved very easily following the Flux Architecture.

Your widgets can listen to a common Store. When you click on a <button/> in <Widget1/>, it would fire an ACTION which would update value of a variable in Store. Both the widgets (<Widget1/> and <Widget2/>) would be listening to the change in the same store Store and would update themselves once the Store updates.

//Widget    
class Widget extends React.Component{
  componentWillMount(){
    Store.addChangeListener(this.handleStoresChanged);
  }
  componentWillUnmount(){ //removeChangeListener }
  handleStoresChanged(){
    let newCount = Store.getNewCount();
    this.setState({ count: newCount });
  }
  addCount(){
    dispatch('ADD_2', {});
  }
  render(){
   return(
    <div>
      <button onclick={this.addCount.bind(this)}>Add 2 to count</button>
      {this.state.count}
    </div>
   )
  }
}

// Widget1 and Widget2 would have the same structure and can extend the above class

Store would then listen to ADD_2 action and then add 2 to a variable called _count inside store. The getNewCount() function inside this store will return the value of _count variable. Since both the widgets are listening to the same store, an action of clicking the button on any widget would change the store and this change will be reflected in both the widgets.

Upvotes: 3

Related Questions