上下文 API 是一種很好的方法,讓我們在應用程式中傳遞狀態,而不需要使用 props。

上下文 API 的引入可以讓我們在應用程式中傳遞狀態 (並且允許該狀態在多個組件之間更新),而不需要使用 props。

React 團隊建議,在只有幾個層級的子組件需要傳遞狀態的情況下,仍然使用 props,因為相比於上下文 API,props 是更簡單的 API。

在許多情況下,使用上下文 API 可以避免使用 Redux,大大簡化我們的應用程式,同時學習如何使用 React。

它是如何運作的呢?

你可以使用 React.createContext() 創建一個上下文 (Context):

const { Provider, Consumer } = React.createContext()

然後,你可以創建一個包裹組件 (wrapper component),並返回一個 Provider 組件,在其中加入所有你希望訪問上下文的組件:

class Container extends React.Component {
 constructor(props) {
 super(props)
 this.state = {
 something: 'hey'
 }
 }

 render() {
 return (
 <Provider value={{ state: this.state }}>{this.props.children}</Provider>
 )
 }
}

class HelloWorld extends React.Component {
 render() {
 return (
 <Container>
 <Button />
 </Container>
 )
 }
}

我將這個組件命名為 Container,因為它將是一個全局的提供者 (Provider)。你也可以創建更小的上下文 (Context)。

在被 Provider 包裹的組件中,你可以使用 Consumer 組件來使用該上下文:

class Button extends React.Component {
 render() {
 return (
 <Consumer>
 {context => <button>{context.state.something}</button>}
 </Consumer>
 )
 }
}

你還可以將函數傳遞給 Provider 的 value,並且這些函數將被 Consumer 使用以更新上下文的狀態:

<Provider value={{
 state: this.state,
 updateSomething: () => this.setState({something: 'ho!'})}}>
 {this.props.children}
</Provider>

/* ... */
<Consumer>
 {(context) => (
 <button onClick={context.updateSomething}>{context.state.something}</button>
 )}
</Consumer>

你可以在 這個 Glitch 中看到這個示例。

你可以創建多個上下文,將狀態分佈在多個組件中,同時使它可以被任何你想要的組件訪問。

當在多個文件中使用時,你可以在一個文件中創建上下文,然後在所有使用它的地方導入:

//context.js
import React from 'react'
export default React.createContext()

//component1.js
import Context from './context'
//... 使用 Context.Provider

//component2.js
import Context from './context'
//... 使用 Context.Consumer