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

Reactjs 一个反应组分。两个HOC。如何使setState正确更新道具?,reactjs,higher-order-components,Reactjs,Higher Order Components,给定一个标准compose函数和一个“div”组件,您将如何编写这两个HOC,以便: “div”元素以20px的绿色框开始,然后单击,变成50px的蓝色框 -a:将状态与道具合并,b:触发状态更改,由单独的HOC处理 更新程序将状态映射到道具,并设置默认状态 dispatcher HOC接受一个函数,以在单击时获取新状态 下面的示例用于获得一个绿色框,并正确地触发处理程序。更新仅在Dispatcher HOC的状态下发生。更新程序的状态保持不变,其道具也保持不变 我真的很想知道发生了什么。在

给定一个标准compose函数和一个“div”组件,您将如何编写这两个HOC,以便:

  • “div”元素以20px的绿色框开始,然后单击,变成50px的蓝色框
  • -a:将状态与道具合并,b:触发状态更改,由单独的HOC处理
  • 更新程序将状态映射到道具,并设置默认状态
  • dispatcher HOC接受一个函数,以在单击时获取新状态
下面的示例用于获得一个绿色框,并正确地触发处理程序。更新仅在Dispatcher HOC的状态下发生。更新程序的状态保持不变,其道具也保持不变

我真的很想知道发生了什么。在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');

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

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}/>
  }
}
从而呈现绿色框

触发单击后

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}/>
  }
}
当然,它仍然渲染第一个(蓝色框),但为了避免这种情况,请尝试将
HOCUpdater
的渲染方法更改为:

return createElement(BaseComponent,{...this.state});
并添加一个
组件willreceiveprops
方法,因此您的
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});
    }
  }
}

谢谢你详尽的回答,阿明!Re:“好吧,只要将this.props更改为this.state在Dispatcher中,你就会看到神奇的发生。”同意。这难道不意味着调度器现在也在将状态映射到道具吗?将状态合并到调度器中的道具是有效的。然而,这正是我试图通过创建两个HOC来分离的问题。如果我理解现在发生的事情,那么在渲染函数中,道具是在HOC之间复制的,但是状态和构造函数上的其他属性不是。合并来自不同HOC的状态的唯一方法是将每个HOC的状态合并到PROP中。这符合你的理解吗?
return createElement(BaseComponent,{...this.state});
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});
    }
  }
}