event bus in React?

Event Bus is only a Global Function Register, can you use it

class _EventBus {

    constructor() {
        this.bus = {};
    }

    $off(id) {
       delete this.bus[id];
    }

    $on(id, callback) {
        this.bus[id] = callback;
    }

    $emit(id, ...params) {
        if(this.bus[id])
            this.bus[id](...params);
    }
}

export const EventBus = new _EventBus();

The export const prevent multiple instances, making the class static


In the case of two sibling components, you would hold the state in the parent component and pass that state as a prop to both siblings:

class ParentComponent extends Component {
  state = {
   specialProp: "bar"
  }

  changeProp = () => {
   // this.setState.. 
  }
  render() {
    return (
      <div>
        <FirstSibling specialProp={this.state.specialProp} />
        <SecondSibling changeProp={this.changeProp} specialProp={this.state.specialProp} />
      </div>
    );
  }
}

For those that are still searching, look at this article: https://www.pluralsight.com/guides/how-to-communicate-between-independent-components-in-reactjs

The solution uses:

document.addEventListener for $on;

document.dispatchEvent for $emit;

document.removeEventListener for $off;

In my use case I had a component that contained a Refresh button that would trigger a data refresh in other components.

I did everything as it was presented in the article. In case you're using React with Functional Components, you might want to use the following useEffect:

  useEffect(() => {
    // The component might unmount when the request is in progress.
    // Because of this an error will appear when we'll try to 'setData'.
    let isMounted = true

    const getData = () => {
      reqData(db, path)
        .then(result => {
          if (isMounted) {
            setData(result) // This is a useState
          }
        })
    }

    eventBus.on('refreshData', (data) => {
      getData()
    })

    getData()

    return () => {
      isMounted = false
      eventBus.remove('refreshData')
    }

    // Do not change the end of this useEffect. Keep it as it is. It simulates componentDidMount.
    // eslint-disable-next-line
  }, [])