陷阱

我們建議將元件定義為函式而不是類別。 瞭解如何遷移。

PureComponent 類似於 Component,但它會跳過 props 和 state 相同的重新渲染。React 仍然支援類別元件,但我們不建議在新程式碼中使用它們。

class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}

參考

PureComponent

要跳過 props 和 state 相同的類別元件重新渲染,請繼承 PureComponent 而不是 Component:

import { PureComponent } from 'react';

class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}

PureComponentComponent 的子類別,並支援 所有 Component API。 繼承 PureComponent 等同於定義一個自訂的 shouldComponentUpdate 方法,該方法會淺層比較 props 和 state。

請參閱以下更多範例。


用法

跳過類別元件不必要的重新渲染

React 通常會在父組件重新渲染時,重新渲染其所有子組件。為了優化效能,您可以建立一個組件,只要它的新 props 和 state 與舊的 props 和 state 相同,React 就不會在父組件重新渲染時重新渲染它。 類別組件 (Class components) 可以透過繼承 PureComponent 來選擇使用這種行為。

class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}

一個 React 組件應該始終具有 純粹的渲染邏輯 (pure rendering logic)。 這表示如果它的 props、state 和 context 沒有改變,它必須返回相同的輸出。透過使用 PureComponent,您是在告訴 React 您的組件符合此要求,因此只要它的 props 和 state 沒有改變,React 就不需要重新渲染它。但是,如果它正在使用的 context 發生變化,您的組件仍然會重新渲染。

在此範例中,請注意 Greeting 組件會在 name 更改時重新渲染(因為它是其 props 之一),但在 address 更改時不會重新渲染(因為它沒有作為 prop 傳遞給 Greeting)。

import { PureComponent, useState } from 'react';

class Greeting extends PureComponent {
  render() {
    console.log("Greeting was rendered at", new Date().toLocaleTimeString());
    return <h3>Hello{this.props.name && ', '}{this.props.name}!</h3>;
  }
}

export default function MyApp() {
  const [name, setName] = useState('');
  const [address, setAddress] = useState('');
  return (
    <>
      <label>
        Name{': '}
        <input value={name} onChange={e => setName(e.target.value)} />
      </label>
      <label>
        Address{': '}
        <input value={address} onChange={e => setAddress(e.target.value)} />
      </label>
      <Greeting name={name} />
    </>
  );
}

陷阱

我們建議將元件定義為函式而不是類別。 瞭解如何遷移。


替代方案

PureComponent 類別組件遷移到函式

我們建議在新程式碼中使用函式組件而不是 類別組件。如果您有一些現有的類別組件正在使用 PureComponent,以下是如何轉換它們的方法。這是原始碼:

import { PureComponent, useState } from 'react';

class Greeting extends PureComponent {
  render() {
    console.log("Greeting was rendered at", new Date().toLocaleTimeString());
    return <h3>Hello{this.props.name && ', '}{this.props.name}!</h3>;
  }
}

export default function MyApp() {
  const [name, setName] = useState('');
  const [address, setAddress] = useState('');
  return (
    <>
      <label>
        Name{': '}
        <input value={name} onChange={e => setName(e.target.value)} />
      </label>
      <label>
        Address{': '}
        <input value={address} onChange={e => setAddress(e.target.value)} />
      </label>
      <Greeting name={name} />
    </>
  );
}

當您將 此組件從類別轉換為函式時,請將其包裝在 memo 中:

import { memo, useState } from 'react';

const Greeting = memo(function Greeting({ name }) {
  console.log("Greeting was rendered at", new Date().toLocaleTimeString());
  return <h3>Hello{name && ', '}{name}!</h3>;
});

export default function MyApp() {
  const [name, setName] = useState('');
  const [address, setAddress] = useState('');
  return (
    <>
      <label>
        Name{': '}
        <input value={name} onChange={e => setName(e.target.value)} />
      </label>
      <label>
        Address{': '}
        <input value={address} onChange={e => setAddress(e.target.value)} />
      </label>
      <Greeting name={name} />
    </>
  );
}

注意事項

PureComponent 不同,memo 不會比較新的和舊的 state。在函式組件中,使用相同的 state 呼叫 set 函式 預設情況下已可防止重新渲染,即使沒有 memo 也一樣。