React中的子组件应该如何以干净和可维护的方式相互通信?

时间:2016-08-11 09:13:09

标签: javascript reactjs typescript architecture

我是React的新手,我正在努力了解子组件之间相互通信的简洁方法。

在一个简单的组件中,我知道我可以利用props将数据传递给子节点,并让子节点的回调将数据传递回父组件。 enter image description here

在稍微复杂的情况下,当我在父组件中有多个子组件时,子组件之间的通信会有点混乱。我不确定我应该为同级别的儿童组件做些什么来相互沟通。 enter image description here

在我的情况下,我决定,也许,我可以使用states。所以我将在父组件中有一个state值,并将其传递给子组件的道具。类似地,父组件中的回调处理程序(从子组件调用)将有助于相应地设置状态,以便通过React的绑定将状态值从一个子节点传递到另一个子节点。 enter image description here

伪代码看起来像:

//Inside Parent Component
constructor() {
   //initialise state for the child components
   this.setState({testList: []});
}

render() {
    return (
        <div>
            <ChildA onSomething={this.onSomethingHandler} testList={this.state.testList} />
            <ChildB onSomethingElse={this.onSomethingElseHandler} testList={this.state.testList} />
        </div>
    );
}

onSomethingHandler(evt):void {
    if(blah.blah.blah) this.setState({testList: this.state.testList.splice().push(evt.value)};
}

onSomethingElseHandler(evt):void {
    //Some other complex biz logic...
    if(blah.blah.blah) this.setState({testList: this.state.testList.splice().push(somethingOtherStuffDueToLogic)};
}

//Inside ChildA Component
export IChildAProps {
    onSomething: (evt)=>void
}

render() {
    //Do some logic from the value in testList property
    if(this.state.testList == blah blah)...

    return (
        <button onClick={this.props.onSomething({id:321, value:"wassup! I'm ChildA."})}>ChildA</button>
    )
}

//Inside ChildB Component
export IChildBProps {
    onSomethingElse: (evt)=>void
}

render() {
    //Do some logic from the value in testList property
    if(this.state.testList == blah blah)...

    return (
        <button onClick={this.props.onSomething({id:123, value:"yo! I'm ChildB."})}>ChildB</button>
    )
}

此时,我开始想知道2个处理程序方法中的逻辑,即Parent组件中的onSomethingHandler()onSomethingElseHandler()是否应该实际存在于子组件本身中?我想到了这一点,因为这些逻辑看起来像子组件应该自己处理它们的目的。父组件不应该为它们执行,否则它可能会变得混乱。但我别无选择,因为我正在处理他们的沟通。除此之外,我还创建了一个新的状态,只是为了让他们进行交流。

到目前为止,这仍然相对容易管理。但是在我自己的实验中,它已进入一个阶段,我将子组件嵌套在另一个子组件中,这些子组件需要在相同(或有时不同)级别的其他子组件之间进行通信。使用状态进行通信也意味着我在所有地方都有许多状态,这对我来说不是一个好主意。并且父组件最终得到了大量凌乱的回调处理程序方法来管理组件树上下的所有数据传播。

情况非常混乱,我最多可以将其说明为: enter image description here

你可以在上面的插图中看到,ChildB最终还有另一个州,只是为了帮助在其子组件之间传递信息。

我确定我错过了一些我应该了解的关于React的内容。我在父组件中的回调似乎有点太多,只是为了处理数据传播。我应该如何以干净和可维护的方式真正组织儿童组件的沟通?

3 个答案:

答案 0 :(得分:6)

每个React程序员都会在某个时间点撞到这堵墙。我也是。答案是使用Redux进行状态管理。您已经体验过使用React的原生状态是多么乏味。

Redux是一种状态管理机制,可以与React一起使用。所以你不会使用React的状态,而是使用Redux。

Redux提供单个存储,存储整个应用程序的状态。您可以使用connect()方法访问组件中的状态。

但有一点需要注意。并非所有反应组件都连接到Redux存储。有两种类型的组件 -

  • 智能/连接组件:连接到redux商店
  • 哑组件:取决于连接的组件

我们的想法是通过React的props将状态从redux存储传递到Connected组件。连接的组件可以直接从商店消耗状态。哑组件不直接连接到redux商店。连接的组件也通过props将状态传递给哑​​组件。所以你看,React的状态完全被绕过了。现在,如果要更改状态,必须发生以下事件 -

  1. 从智能/哑组件触发事件。
  2. Actions已发送至store
  3. Reducers根据actions创建新状态。
  4. 新状态将存储在store
  5. Store会通过connect()props
  6. 将新状态返回到已连接的组件
  7. Dumb组件将通过props
  8. 从连接的组件接收新状态

    什么是行动和减少?

    操作只不过是描述如何更改状态的javascript对象。

    Reducer是一个“纯粹”的函数,它根据调度到商店的操作构建并返回新的状态树。

    Redux - http://redux.js.org/

    Redux-thunk - https://github.com/gaearon/redux-thunk

    Redux-saga - https://github.com/yelouafi/redux-saga

答案 1 :(得分:1)

大多数时尚方式都是使用Redux.js(或flux.js)来表示您的子组件状态。

http://redux.js.org/

如果你不喜欢调用第三方js。您可以使用refs属性:

https://facebook.github.io/react/docs/more-about-refs.html

答案 2 :(得分:0)

我们可以使用react context API

  

上下文提供了一种通过组件树传递数据的方法,而不必在每个级别手动传递道具

还要注意,马克·埃里克森(Mark Erikson)在他的blog中提到过,

  

是的,新的上下文API对于将数据传递到深度嵌套的组件将非常有用-这正是它的设计目的。

     

如果您仅使用Redux来避免传递道具,则上下文可以替换Redux-但是您可能一开始就不需要Redux。

     

上下文还没有提供Redux DevTools,跟踪状态更新的功能,添加中央化应用程序逻辑的中间件以及Redux启用的其他强大功能之类的功能。

要处理您提到的场景,上下文API是一个不错的选择,并且您不必为此使用其他库。