一个反应组件。两个HOC。如何使setState正确更新道具?

时间:2017-08-28 19:52:28

标签: reactjs higher-order-components

给定一个标准的撰写功能和一个' div'组件,你会如何编写两个HOC:

  • ' div' element以20px绿色框开头,然后点击,变成50px的蓝色框。
  • 关注 - a:将状态与道具合并,b:触发状态更改,由不同的HOC处理。
  • 更新程序HOC将状态映射到props,并设置默认状态
  • 调度员HOC接受一个函数来点击
  • 获取新状态

以下示例适用于获取绿色框,并正确触发处理程序。更新仅发生在Dispatcher HOC状态。更新者HOC的状态保持不变,其道具也是如此。

我真的很想知道发生了什么。翻转两个HOC' compose中的顺序导致处理程序不被设置。由于他们都在{...this.props}合并,这对我来说没有意义。猜猜我不了解多个HOC如何合并道具和状态。

const HOCDispatcher = myFunc => BaseComponent => {
  return class Dispatcher extends React.Component {
    constructor(props,context){
      super(props,context);
      this.handlerFn = (event)=>{this.setState(myFunc)}
    }
    render(){
      return createElement(BaseComponent,{...this.props,onClick:this.handlerFn});
    }
  }
}

const HOCUpdater = defaultState => BaseComponent => {
  return class Updater extends React.Component {
    constructor(props,context){
      super(props,context);
      this.state = Object.assign({},defaultState,this.state);
    }
    render(){
      return createElement(BaseComponent,{...this.props,...this.state});
    }
  }
}

const MyComponent = compose(
  HOCDispatcher(()=>({
    style:{width:'50px',height:'50px',background:'blue'}
  })),
  HOCUpdater({
    style:{width:'20px',height:'20px',background:'green'}
  }),
)('div');

1 个答案:

答案 0 :(得分:1)

如果您尝试以不太复杂的结构简化或编译代码,您可以更好地理解它:

MyComponent的初始版本

tools:replace="android:label"

其中const MyComponent= class Dispatcher extends React.Component { constructor(props,context){ super(props,context); this.handlerFn = (event)=>{this.setState({ style:{width:'50px',height:'50px',background:'blue'} })} } render(){ return <HOCUpdater onClick={this.handlerFn}/> } } 也呈现为:

HOCUpdater

这样渲染绿框。

触发点击后

class Updater extends React.Component {
  constructor(props,context){
    super(props,context);
    this.state = {
      style:{width:'20px',height:'20px',background:'green'}
    };
  }
  render(){
    return <div style:{width:'20px',height:'20px',background:'green'}/>;
  }
}

如果你注意渲染,它仍然是相同的,因为const MyComponent= class Dispatcher extends React.Component { constructor(props,context){ super(props,context); this.handlerFn = (event)=>{this.setState({ style:{width:'50px',height:'50px',background:'blue'} })}; this.state= { style:{width:'50px',height:'50px',background:'blue'} }; } render(){ return <HOCUpdater onClick={this.handlerFn}/> } } 没有改变,它仍然是空的。因此,没有改变框的样式,而this.props的状态发生了变化!

你看到你哪里出错了吗?好吧,只需在Dispatcher中将this.props更改为this.state,您就会看到神奇的事情发生。

但等等,还有更多!

如果您有这样的代码行,会发生什么?

Dispatcher

好吧,它仍然呈现第一个(蓝色框),但为了避免这种情况,请尝试将createElement('div',{ style:{width:'50px',height:'50px',background:'blue'}, style:{width:'20px',height:'20px',background:'green'} }); 的呈现方法更改为:

HOCUpdater

并添加了return createElement(BaseComponent,{...this.state}); 方法,因此您的componentWillReceiveProps将如下所示:

HOCUpdater