使用 react Context API 的正确姿势

本文介绍一下 React 中常见的 Context API 的使用方式。在使用 Context API 之前,我们还需要知道为啥要使用。❓
为啥要用 Context API
考虑到组件有可能 层层嵌套 ,在传 props 的过程中,如果书写大量的 …props 或 propName={this.props.propValue} 会导致代码灰常丑陋 ????:

一层一层下来就像这样:
<App>
<Switcher toggleState={this.state.toggle}>
<Pannel toggleState={props.toggleState}>
<div onClick={handleClick}>{props.toggleState ? ‘✔’ : ‘❌’}
所以引入 Context API 就可以直接通过上下文跨层级获取数据:
如何使用

然后创建 provider ????
首先要引入 React 内置的 React Context API ????
最后创建 consumer ????

创建 Provider
增加一个名为 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
上面的代码主要分为三大部分:
// 创建 Context
const ToggleContext = createContext()

// 创建 Provider
export class ToggleProvider extends React.Component {}

// 创建 Consumer
export cnost ToggleConsumer = ToggleContext.Consumer
我们理一下步骤????‍

首先,我们需要引入 createContext 上下文并调用,传入我们希望在其他层级组件中使用的 state 和改变 state 的方法,注意这里的 state 和方法只是一个“骨架”,后面的 Provider 会覆盖
接下来创建 Provider 这里头维护真正的 state,并通过 render 函数里面的 Context.Provider 组件的 value 属性提供这些方法
然后创建 Consumer,直接导出 Context.Consumer 给外部使用即可

使用 Provider
ToggleProvider 组件包装了一系列共享的状态,为了使用这些组件的状态,我们直接将其添加到 App 组件中:
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 提供的 state
使用 Consumer

通过 Consumer 直接使用 props 传递的 state 属性在 render 函数中渲染即可
如果需要调用方法,则可调用 props 传递的函数

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 调用即可
小结
另外附上一个简易版的 Context:

通过 createContext 创建一个名为 color 的 context
通过 Provider 的 value 属性传值
通过 Consumer 的 props 接收值

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;

参考:
https://blog.usejournal.com/s…

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理