本文介紹一下 React 中常見的 Context API 的使用方式。在使用 Context API 以前,咱們還須要知道爲啥要使用。❓react
考慮到組件有可能 層層嵌套 ,在傳 props 的過程當中,若是書寫大量的 ...props
或 propName={this.props.propValue}
會致使代碼灰常醜陋 🤢:api
一層一層下來就像這樣:markdown
<App>
<Switcher toggleState={this.state.toggle}>
<Pannel toggleState={props.toggleState}>
<div onClick={handleClick}>{props.toggleState ? '✔' : '❌'}
複製代碼
因此引入 Context API 就能夠直接經過上下文跨層級獲取數據:ide
增長一個名爲 ToggleContext.js
的文件做爲上下文📜,裏頭定義一系列須要跨層級使用的 state 和 function函數
import React, { createContext } from 'react' // 1. 使用 createContext 建立上下文 const ToggleContext = createContext({ toggle: true, handleToggle: () => {} }) // 2. 建立 Provider export class ToggleProvider extends React.Component { // 注意書寫順序;handleToggle 做爲箭頭函數不能 bind 所以須要寫在上面;若是不喜歡這樣的順序則能夠書寫普通函數放在下面但記得 bind handleToggle = () => { this.setState({ toggle: !this.state.toggle }) } // 2-1. 重寫 state state = { toggle: true, handleToggle: this.handleToggle } render() { // 2-2. 經過 Provider 組件的 value 將 state 提供出去 return ( <ToggleContext.Provider value={this.state}> {this.props.children} </ToggleContext.Provider> ) } } // 3. 建立 Consumer export const ToggleConsumer = ToggleContext.Consumer 複製代碼
上面的代碼主要分爲三大部分:this
// 建立 Context const ToggleContext = createContext() // 建立 Provider export class ToggleProvider extends React.Component {} // 建立 Consumer export cnost ToggleConsumer = ToggleContext.Consumer 複製代碼
咱們理一下步驟🏃spa
createContext
上下文並調用,傳入咱們但願在其餘層級組件中使用的 state
和改變 state
的方法,注意這裏的 state
和方法只是一個「骨架」,後面的 Provider
會覆蓋Provider
這裏頭維護真正的 state
,並經過 render
函數裏面的 Context.Provider
組件的 value
屬性提供這些方法Consumer
,直接導出 Context.Consumer
給外部使用便可ToggleProvider
組件包裝了一系列共享的狀態,爲了使用這些組件的狀態,咱們直接將其添加到 App 組件中:code
import React from 'react'; import { ToggleProvider } from './ToggleContext' // 1. 獲取 Provider function App() { // 2-1. 使用 ToggleProvider 組件 // 2-2. 若是有其餘組件同樣能夠共享 state return ( <ToggleProvider> <Switcher></Switcher> {/* 其餘組件仍然能夠經過 props 訪問到共享的 state */} </ToggleProvider> ); } // ... export default App; 複製代碼
使用 Provider 比較簡單直接做爲父組件包裹在上層便可。若是組件內部有其餘多個組件,這些組件均可以共享 Provider 提供的 stateorm
import React from 'react'; import { ToggleProvider, ToggleConsumer } from './ToggleContext' // 1. 獲取 Provider 和 Consumer function App() { return ( <ToggleProvider> <Switcher></Switcher> </ToggleProvider> ); } const Switcher = () => { return <Pannel /> } const Pannel = () => { // 在多個層級內直接經過 props 獲取 state 和方法,調用方法改變 state return ( <ToggleConsumer> {({ toggle, handleToggle }) => <div onClick={() => handleToggle()}>{ toggle ? '✔' : '❌'}</div>} </ToggleConsumer> ) } export default App; 複製代碼
直接在子組件內部經過 props 調用便可blog
另外附上一個簡易版的 Context:
import React, { createContext } from "react";
const { Provider, Consumer } = createContext("color"); // 建立 Context 引用 Provider 和 Consumer
class DeliverComponent extends React.Component {
// 維護一個 state
state = {
color: 'orange',
handleClick: () => {
this.setState({ color: 'red' })
}
}
render() {
return (
<Provider value={this.state}>
<MidComponent />
</Provider>
)
}
}
const MidComponent = () => <Receiver />; // 中間包含多層級的組件
const Receiver = () => ( // 須要使用的後代元素使用 Consumer
<Consumer>
{({ color, handleClick }) => <div style={{ color }} onClick={() => { handleClick() }}> Hello, this is receiver.</div>}
</Consumer>
);
const App = () => <DeliverComponent />;
export default App;
複製代碼
參考: