【问题标题】:event bus in React?React 中的事件总线?
【发布时间】:2018-11-16 00:31:47
【问题描述】:

我主要使用 Vue,最近才开始使用 React。到目前为止很喜欢它,它在很多方面与 Vue 非常相似,这使得学习变得更容易。

现在,让我们考虑两个兄弟组件。当组件二发生某些事情时,我想触发组件一中的某些事情。在 Vue 中,您只需绑定 window.bus = new Vue,然后在其中一个组件 bus.$emit('event') 中发出并在第二个组件 bus.$on('event', this.doSth)mounted() 中绑定。

如何在 React 中实现这一点?

【问题讨论】:

  • React 方法是让组件的父级将回调传递给组件调用的组件之一。然后父级对数据进行处理并重新渲染,将数据传递给另一个组件。当然,您也可以只使用任何 pubsub 库并直接连接组件。这完全取决于你。
  • 谢谢你的回答,我也去看看pubsub库。

标签: javascript reactjs


【解决方案1】:

Event Bus只是一个全局函数寄存器,你能用吗

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();

export const 防止多个实例,使类静态

【讨论】:

  • 不鼓励仅使用代码的答案。请添加一些解释,说明这是如何解决问题的,或者这与现有答案有何不同。 From Review
【解决方案2】:

在两个兄弟组件的情况下,您将在父组件中保存状态并将该状态作为道具传递给两个兄弟组件:

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>
    );
  }
}

【讨论】:

    【解决方案3】:

    还在搜索中的可以看这篇文章:https://www.pluralsight.com/guides/how-to-communicate-between-independent-components-in-reactjs

    解决方案使用:

    document.addEventListener$on

    document.dispatchEvent$emit;

    document.removeEventListener$off

    在我的用例中,我有一个包含刷新按钮的组件,该按钮会触发其他组件中的数据刷新。

    我按照文章中的说明做了所有事情。如果您将 React 与功能组件一起使用,您可能需要使用以下 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
      }, [])
    

    【讨论】:

      【解决方案4】:

      父组件可以管理state和子组件在通过props向下传递时使用的方法。

      以下示例增加一个计数。 SibOne 显示计数,SibTwo 中的按钮增加计数。

      class App extends Component {
          constructor(props) {
              super(props);
              this.state = {
                  count: 0
              };
          }
          incrementCount = () => {
              this.setState({
                  count: this.state.count + 1
              });
          }
          render() {
              return (
                  <div className="App">
                      <SibOne count={this.state.count}/>
                      <SibTwo incrementCount={this.incrementCount}/>
                  </div>
              );
          }
      }
      
      const SibOne = props => <div>Count: {props.count}</div>;
      
      const SibTwo = props => (
          <button onClick={props.incrementCount}>
              Increment Count
          </button>
      );
      

      演示:https://codesandbox.io/s/zqp9wj2n63

      更多关于组件和道具https://reactjs.org/docs/components-and-props.html

      【讨论】:

      • 虽然这不是事件总线。
      【解决方案5】:

      rxjs 是您可以探索的另一种选择。检查这是否可以帮助您,因为他们提供可观察和基于事件的程序。它也在做类似 Eventbus 在 vuejs 中所做的事情。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-20
        • 1970-01-01
        • 2020-01-04
        • 2020-12-07
        相关资源
        最近更新 更多