使用Promises连接React组件

时间:2017-10-19 18:47:06

标签: reactjs promise redux

我想出了一个React问题的解决方案,想看看人们的想法。

问题:我有一个非常大的表单组件,其中包含许多子表单,每个子表单都可以展开和最小化。父表单组件已经在管理大量状态,因为所有子表单都向其报告其输入值。还有一个“ErrorBubble”组件。只要表单经过验证并且出现错误,就会出现ErrorBubble并找到表单中的第一个无效字段并移动到该字段。 ErrorBubble还必须在表单大小发生变化时动态更新其位置,如果您最小化或扩展任何子表单,则会发生这种情况。所以,问题是,如何让每个子表单与需要重新定位的ErrorBox进行通信?

传统解决方案:只需让父表单组件管理所有状态即可。每个子表单都会将其展开状态的任何更改报告给父组件,这会导致重新呈现包括ErrorBubble在内的所有内容。

缺点:父组件已经有很多方法并说明它正在管理,我不想添加更多。强制重新呈现整个父表单组件

Redux解决方案:让每个子表单调度一个redux操作,并将ErrorBubble连接到Redux存储。

缺点:要创建的大量样板文件。必须为此创建一个reducer和一个redux商店。必须设计redux动作。必须将ErrorBubble连接到redux。在每个子窗体调整大小时更新redux存储可能效率不高吗?

我的解决方案:我有一个DeferredTask自定义对象帮助器。我在父窗体组件的构造函数中创建它的一个实例,并将其保存为状态。这是自定义对象:

export class DeferredTask {
  constructor () {
    this.promise = new Promise((resolve, reject) => {

      this.resolve = resolve
      this.reject = reject

      this.reset = function () {
        this.promise = new Promise((resolve, reject) => {

          this.resolve = resolve
          this.reject = reject

        })
      }
    })
  }
}

然后我将this.state.deferredTask传递给所有子表单,并将ErrorBubble传递给prop。

每当ErrorBubble挂载时,它会运行一个侦听此deferredTask来解析的方法,当它卸载时,它会拒绝任务将其关闭,以便它不会永久保留:

componentDidMount() {
  this.repositionErrorBubble()
  this.deferredTask()
}

deferredTask = () => {
  this.props.deferredTask.reset()
  this.props.deferredTask.promise
    .then(()=>{
      if(this._calledComponentWillUnmount) {
        return
      }
      this.repositionErrorBubble()
      this.deferredTask()
    })
}

componentWillUnmount () {
  this.props.deferredTask.reject()
}

每个子表单都有:

componentDidUpdate () {
  this.props.deferredTask.resolve()
}

现在,每次任何子表单更新时,它们都会解析promise并且ErrorBubble会运行then()。它需要检查是否计划卸载ErrorBubble组件,因为您无法更新卸载组件的状态。否则,它运行代码以重新定位ErrorBubble,然后重置promise并开始再次收听它。

优点:只创建一个状态并从父表单组件传递一个支柱。连接这些组件的相当小的代码表面区域。不必通过常规道具渠道进行更新。 componentWillReceiveProps已经臃肿了很多其他检查。

它像一个准酒吧子模式但更整洁?

你们觉得怎么样?这是反模式,因为数据是水平传递而不是垂直传递的?请记住,deferredTask对象仍然可以在父组件中作为状态使用并且正在向下传递...这会使它更好吗?

使用异步承诺是否有陷阱?它能咬我的屁股吗?因为触发解决方案的唯一事情是连续的用户交互,并且在每次交互后重置承诺,所以它不应该引起任何混淆,承诺正在解决它吗?到目前为止,我已经尝试将子窗体大小调整为垃圾邮件并且没有造成任何问题。

有没有更好的方法可以使用React?

0 个答案:

没有答案