簡體   English   中英

React組件是否會深入比較道具以檢查是否需要重新渲染?

[英]Does a React component deeply compare props to check if rerender is needed?

我想知道在嘗試確定是否需要重新渲染時,擴展React.Component的React組件React.Component深深地比較對象。

例如,給定

const Foo = ({ bar }) => {
  return <div>{bar.baz}</div>
}

class App extends React.Component {
  constructor() {
    super()
    this.state = { bar: { baz: 1} }
  }

  render() {
    return <Foo bar={this.state.bar} />
  }
}

如果內部App ,狀態bar變為{baz: 2}確實<Foo />深深比較以前的支柱bar和新接收到的支柱?

順便提一下, PureComponent的文檔

擴展PureComponent ...或者,考慮使用不可變對象來促進嵌套數據的快速比較。

但是沒有詳細介紹。 有任何想法嗎?

除非您自己實現了shouldComponentUpdate生命周期方法,否則擴展React.Component的組件React.Component重新渲染周期之前不會比較道具,它會比較前一個和當前的Virtual DOM來決定重新渲染的內容。

使用React.PureComponent擴展的組件也不會將prevProps和prevState的狀態與prevState進行深度比較,但是如果需要重新渲染則需要執行淺比較來決定是否需要重新渲染。

對於v16.6.0以后的Functional component ,React引入了一個高階函數React.memo ,可用於使函數組件表現為React.PureComponent

根據文件

React.memo是一個更高階的組件。 它與React.PureComponent類似,但是對於函數組件而不是類。

它可以像

 const MyComponent = React.memo(function MyComponent(props) { /* render using props */ }); 

如果你的函數組件在給定相同的道具的情況下呈現相同的結果,你可以在調用React.memo時將其包裝起來,以便在某些情況下通過記憶結果來提高性能。 這意味着React將跳過渲染組件,並重用最后渲染的結果。

默認情況下,它只會shallowly compare complex objects props對象中的shallowly compare complex objects對象。 如果要控制比較,還可以提供自定義比較函數作為第二個參數。

'Extend PureComponent'被引用脫離了背景。 文檔說的相反,

只有在您希望擁有簡單的道具和狀態時才能擴展PureComponent

因為

React.PureComponent的shouldComponentUpdate()只是淺淺地比較對象。 如果這些包含復雜的數據結構,則可能會產生更深層次差異的假陰性。

React組件不會比較props,除非它們實現了shouldComponentUpdate ,就像PureComponent一樣。 可以使用完全相同的prop( ===相等)重新渲染組件。

如果狀態發生變異但未被強制更新(這是反模式),則不會重新渲染子項。

如果狀態發生變異並被強制更新(這是反模式),則會重新呈現子項:

class App extends React.Component {
  componentDidMount() {
     this.state.bar.baz = 2;
     this.setState(state);
  }
  ...    
}

為了限制對深度更改的道具的更新, Foo應該通過深度比較實現shouldComponentUpdate ,例如Lodash isEqual

class Foo extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return !_.isEqual(this.props, nextProps) || this.state !== nextState;
  }
  ...
}

由於深度比較可能代價高昂,因此應運行性能測試以確定其是否提供性能改進。

React非常歡迎不可變狀態和道具,因為它們可以避免這個問題。 如果一個對象以某種方式改變,它應該被另一個對象替換,即狀態更新應該導致新的statestate.bar對象:

class App extends React.Component {
  componentDidMount() {
    this.setState(({ bar })=> ({
      bar: { ...bar, baz: 2 }
    });
  }
  ...    
}

在這種情況下, Foo需要淺淺地比較它作為prop獲得的bar對象,因此它可以是PureComponentReact.memo (另一個答案解釋)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM