2

给定一个标准的 compose 函数和一个 'div' 组件,你将如何编写这两个 HOC:

  • 'div' 元素以 20px 的绿色框开始,然后单击时变为 50px 的蓝色框。
  • -a:将 state 与 props 合并,b:触发 state 更改,由单独的 HOC 处理。
  • updater HOC 将状态映射到 props,并设置默认状态
  • 调度程序 HOC 接受一个函数以在单击时获取新状态

下面的示例用于获取绿色框,并正确触发处理程序。更新仅在 Dispatcher HOC 的状态下发生。updater HOC 的状态保持不变,它的 props 也是如此。

我真的很想知道发生了什么。在 compose 中翻转两个 HOC 的顺序会导致无法设置处理程序。由于他们都合并{...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');
4

1 回答 1

1

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

MyComponent 的初始版本

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}/>
  }
}

WhereHOCUpdater也呈现为:

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.propsthis.statein 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将如下所示:

const HOCUpdater = defaultState => BaseComponent => {
  return class Updater extends React.Component {
    constructor(props,context){
      super(props,context);
      this.state = Object.assign({},defaultState,this.state);
    }
    componentWillReceiveProps(nextProps){
      this.setState(nextProps);
    }
    render(){
      return createElement(BaseComponent,{...this.state});
    }
  }
}
于 2017-08-28T21:25:24.793 回答