2016-11-27 240 views
0

我很好奇,爲什麼在這種情況下做出反應的更新的子組件:爲什麼React調用未更改組件的渲染方法?

function Inner(props) { 
    console.log("Render Inner"); 
    return <div>Inner</div>; 
} 

export class Outer extends React.Component { 

    constructor(props) { 
    super(props); 
    this.state = { 
     active: false 
    }; 
    this.onClick = this.rawOnClick.bind(this); 
    } 

    render() { 
    console.log("Render Outer"); 
    return <div onClick={this.onClick} style={{ backgroundColor: this.state.active ? 'red': 'blue'}}><Inner/></div>; 
    } 

    rawOnClick(event) { 
    this.setState({ active: !this.state.active }); 
    } 
} 


ReactDOM.render(<Outer/>, document.getElementById('app')); 

當組件外被點擊時,內,外的渲染方法被調用。由於組件應該是「純」的,所以不需要調用Inner的渲染方法,是嗎?我甚至可以讓它這樣,如果我重寫我的代碼一點點:

export function Inner(props) { 
    console.log("Render Inner"); 
    return <div>Inner</div>; 
} 

export class Outer2 extends React.Component { 

    constructor(props) { 
    super(props); 
    this.state = { 
     active: false 
    }; 
    this.onClick = this.rawOnClick.bind(this); 
    } 

    render() { 
    console.log("Render Outer"); 
    return <div onClick={this.onClick} style={{ backgroundColor: this.state.active ? 'red': 'blue'}}>{this.props.children}</div>; 
    } 

    rawOnClick(event) { 
    this.setState({ active: !this.state.active }); 
    } 
} 

ReactDOM.render(<Outer2><Inner /></Outer2>, document.getElementById('app')); 

現在,當我點擊該組件只有「Outer2」的渲染方法被調用。這是故意的嗎?這是一項任務優化,還是我錯過了一些重要的事情?

謝謝。

Peter

+0

查看更多文檔後,我發現我想要的東西:我需要:'this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);'在構造函數中,它具有我期望的行爲。我仍然覺得這很奇怪,文檔會一直談論這種「純粹」渲染,然後忽略它(特別是在「功能」組件中)。但我可以處理。謝謝大家。 – ptriller

+0

對不起,我只需要使用'React.PureComponent'作爲基類,並且我有我想要的行爲。 – ptriller

回答

1

這是React的默認行爲。您必須重寫Inner組件中的shouldComponentUpdate()以返回true或false,以確定是否需要再次調用它自己的render()。通常根據當前和下一組道具和狀態之間的差異(如果有的話)做出決定。

在你的例子中,你的內部組件總是返回相同的東西,並且不會受到道具或狀態改變的影響,你可以返回false。

shouldComponentUpdate(nextProps, nextState) { 
    return false; 
}; 

(注意,你必須從內部無狀態的功能轉換成ES6類才能使用這種方法的生命週期)。

在官方的文檔閱讀全文 - https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate

+0

當道具沒有改變時,我只是被默認行爲所困惑,但只是被設置爲相同的值。該文檔說:「默認行爲是重新呈現每個狀態更改....」但由於狀態不會更改所有屬性設置爲相同的值時,我認爲它不會呈現。 – ptriller

1

在第一種情況,外部組件的狀態在觸發點擊事件時發生改變。由於狀態改變,渲染方法被觸發。由於內部組件位於渲染方法內部,因此它也會被渲染並調用內部組件的渲染方法。

由於在第二種情況下,內部組件不在外部組件的渲染方法內,因此即使外部組件的狀態發生更改也不會重新渲染。

只有當你沒有將外部組件的狀態傳遞給內部組件作爲道具時,你的第二種情況纔會起作用。只要你這樣做,一個狀態的關鍵的改變,作爲一個道具傳遞給內部組件將再次觸發內部組件的渲染方法

如果你想傳遞一些東西從外部組件的狀態到內部組件作爲道具並避免不必要的內部組件渲染調用,您將不得不從無狀態的內部組件移動到基​​於類的內部組件,並使用生命週期方法來限制內部組件的渲染方法不被調用

+0

謝謝。我明白,仍然不是我所期望的,因爲React沒有創建一個新的Inner組件實例,所以它可以檢查它沒有改變任何屬性並跳過渲染,因爲純合約是有效的。但是,如果這是事實,那就是這樣。 – ptriller