說明
支持我們

內容

Context 允許您將值傳遞給樹狀結構深處的子項,而無需透過道具將其傳遞給中間的每個元件。一個非常流行的用例是主題。簡而言之,Context 可以被視為在 Preact 中執行 pub-sub 風格更新的方法。

有兩種不同的方式可以使用 Context:透過較新的 createContext API 和舊版的 Context API。兩者之間的區別在於,當中間的元件透過 shouldComponentUpdate 中止渲染時,舊版 API 無法更新子項。這就是我們強烈建議始終使用 createContext 的原因。



createContext

首先,我們需要建立一個可以傳遞的 Context 物件。這是透過 createContext(initialValue) 函式完成的。它會傳回一個 Provider 元件,用於設定 Context 值,以及一個 Consumer 元件,用於從 Context 中擷取值。

initialValue 參數僅在 Context 在樹狀結構中上方沒有相符的 Provider 時使用。這可能有助於孤立地測試元件,因為它避免了建立包裝 Provider 的需要。

const Theme = createContext('light');

function ThemedButton(props) {
  return (
    <Theme.Consumer>
      {theme => {
        return <button {...props} class={'btn ' + theme}>Themed Button</button>;
      }}
    </Theme.Consumer>
  );
}

function App() {
  return (
    <Theme.Provider value="dark">
      <SomeComponent>
        <ThemedButton />
      </SomeComponent>
    </Theme.Provider>
  );
}
在 REPL 中執行

使用 useContext 鉤子是使用 Context 的更簡單方法。

舊版 Context API

我們包含舊版 API 主要基於向後相容性的原因。它已被 createContext API 取代。舊版 API 已知的問題包括,如果中間的元件在 shouldComponentUpdate 中傳回 false,則會阻擋更新。如果您仍然需要使用它,請繼續閱讀。

若要透過 Context 傳遞自訂變數,元件需要有 getChildContext 方法。您可以在其中傳回您想要儲存在 Context 中的新值。可以在函式元件的第二個參數或類別為基礎元件的 this.context 中存取 Context。

function ThemedButton(props, context) {
  return (
    <button {...props} class={'btn ' + context.theme}>
      Themed Button
    </button>
  );
}

class App extends Component {
  getChildContext() {
    return {
      theme: 'light'
    }
  }

  render() {
    return (
      <div>
        <SomeOtherComponent>
          <ThemedButton />
        </SomeOtherComponent>
      </div>
    );
  }
}
在 REPL 中執行