2017-08-28 61 views
2

給定一個標準構建功能和「DIV」成分,你怎麼會寫兩個肝卵圓細胞這樣的:一個反應組件。兩個HOC。如何讓setState正確更新道具?

  • 的「格」元素開始作爲一個20像素的綠框,然後點擊,成爲50像素藍色框。
  • -a:合併狀態和道具以及b:引發狀態變化的問題由單獨的HOC處理。
  • 的更新HOC地圖狀態的道具,並設置爲默認狀態
  • 調度HOC接受一個函數來獲得點擊

下面的例子作品獲得綠色方框,並正確的新狀態引發處理程序。更新只發生在Dispatcher HOC狀態。更新者HOC的狀態保持不變,其道具也一樣。

我很想知道發生了什麼事。翻轉這兩個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'); 

回答

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

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的狀態改變了!

您是否看到您出錯的地方?那麼,只需在Dispatcher中將this.props更改爲this.state,您就會看到奇蹟發生。

但是等等,還有更多!

如果你有這樣的代碼行會發生什麼?

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}); 
    } 
    } 
} 
+0

感謝您的徹底解答阿明!回覆:「好吧,只要將這個.props改爲Dispatcher中的this.state,你就會看到魔法的發生。」同意。 這並不意味着調度員現在也將狀態映射到道具? – Adam

+0

它在調度器中將狀態合併爲道具。但是,這是我想通過創建兩個HOC來分離的問題。如果我明白現在發生了什麼,道具會在渲染函數中的HOC之間複製,但狀態和構造函數上的其他屬性不會。從不同的HOC合併國家的唯一方法是將每個HOC的國家合併爲道具。這符合你的理解嗎? – Adam