2016-08-21 81 views
0

我創建了一個簡單的路由器,它僅根據單個商店的當前狀態進行路由。路由器查看其每個孩子,提取它的狀態select ed,然後根據其when屬性測試路由是否應顯示。在基於簡單商店的路由器中不必要的重新渲染

var Router = React.createClass({ 
    render: function() { 
    const {children, state} = this.props; 
    const activeRoute = React.Children.toArray(children).find(when); 

    return React.createElement(
     activeRoute.props.component, 
     Object.assign(
     {}, 
     activeRoute.props.select(state), 
     { 
      setState: this.props.setState, 
     } 
    ) 
    ); 

    function when(child) { 
     return child.props.when(child.props.select(state)); 
    } 
    } 
}); 

var Route = React.createClass({ 
    getDefaultProps: function() { 
    return { 
     select: identity, 
     when: alwaysTrue, 
    } 
    }, 

    render: function() { 
    throw new Error('Route should never render'); 
    }, 
}); 

這些組件可以像這樣使用。

<Router state={this.state} setState={this.sState}> 
    <Route component={Pets} when={this.onPets} select={this.selectPets} /> 
    <Route component={Home} /> 
</Router> 

當使用why-did-you-update,我發現它重新呈現不必要的。我想消除這些不必要的重新渲染,但是我沒有這樣做。什麼導致重新呈現,我怎樣才能避免它們?

有一個工作演示here。點擊「查看寵物(點擊此處)」,看到控制檯觸發一系列可避免的重新渲染警告。

回答

0

事實證明,why-did-you-update是警告我們,因爲兩個呈現之間的children屬性是相等的,但不是相同的引用。發生這種情況是因爲我們在每個渲染上返回新的React.createElement

要解決此問題,我可以將children轉換爲this.props,this.state,屬性爲app,或者甚至是全局。如果我使用的是es6類而不是createClass,那麼我可以創建一個實例變量。使用這些方法之一,我可以在渲染方法中傳遞children

<Router state={this.state} setState={this.sState} children={routes} /> 

可以找到一個工作示例here