コンテキストは、コンポーネントの各レイヤーにプロップを手動で追加することなく、コンポーネント ツリー間でデータを受け渡す方法を提供します。
1. 使用方法
React.createContext
const MyContext = React.createContext(defaultValue);
Context オブジェクトを作成します。React がこの Context オブジェクトにサブスクライブされたコンポーネントをレンダリングするとき、コンポーネントは、コンポーネント ツリー内でそれ自体に最も近い一致するプロバイダーから現在のコンテキスト値を読み取ります。
コンポーネントが配置されているツリーに一致するプロバイダーがない場合にのみ、defaultValue パラメーターが有効になります。これは、コンポーネントをラップするプロバイダーを使用せずにコンポーネントをテストするのに役立ちます。注: unknown がプロバイダーの値に渡されると、使用側コンポーネントの defaultValue は有効になりません。
コンテキストプロバイダー
<MyContext.Provider value={/* 某个值 */}>
各 Context オブジェクトは Provider React コンポーネントを返します。これにより、使用するコンポーネントはコンテキストの変更をサブスクライブできます。
プロバイダーは値属性を受け取り、それを使用側コンポーネントに渡します。プロバイダーは、複数のコンシューマー コンポーネントと対応する関係を持つことができます。複数のプロバイダーをネストして使用することもでき、内側のレイヤーが外側のレイヤーのデータを上書きします。
コンテキスト.コンシューマ
<MyContext.Consumer>
{value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>
ここで、React コンポーネントはコンテキストの変更をサブスクライブすることもできます。これにより、機能コンポーネントでコンテキストをサブスクライブできるようになります。
2. 応用例
図に示すように、親コンポーネントには、fruit と count という 2 つの変数が定義されています。子コンポーネントは親コンポーネントのフルーツを取得でき、子コンポーネントは親コンポーネントのフルーツを取得して count の値を変更できます。
実装手順は次のとおりです。
2.1 新しいファイル context.js を作成する
Context オブジェクトを作成し、Provider コンテナと Consumer コンテナをエクスポートします。
import { createContext } from 'react'
export const { Provider, Consumer } = createContext()
2.2 新しい親コンポーネントindex.jsを作成する
import React, { Component } from 'react'
import { Provider } from './context' // 引入Provider
import Son from './Son' // 引入子组件
class Main extends Component {
constructor(props) {
super(props)
this.state = {
fruit: 'apple',
count: 0,
}
}
componentDidMount() {}
getContext = () => {
const { fruit, count } = this.state
return {
fruit,
countUtil: {
addCount: num => {
this.setState({
count: count + num,
})
},
delCount: num => {
this.setState({
count: count - num,
})
},
},
}
}
render() {
const { fruit, count } = this.state
return (
// Provider 容器, 其value接收一个getContext方法
<Provider value={this.getContext()}>
父组件 fruit = {fruit}, count = {count}
<hr />
<Son />
</Provider>
)
}
}
export default Main
2.3 新しいサブコンポーネント Son.js を作成する
import React, { Component } from 'react'
import { Consumer } from './context' // 引入Consumer
import GrandSon from './GrandSon' // 引入子子组件
class Main extends Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return (
// Consumer 容器,可以拿到父组件传递下来的 fruit 属性, 并可以展示对应的值
<Consumer>
{context => (
<div>
子组件 fruit={context.fruit}
<hr />
<GrandSon />
</div>
)}
</Consumer>
)
}
}
export default Main
2.4 新しいサブコンポーネント GrandSon.js を作成する
import React, { Component } from 'react'
import { Consumer } from './context' // 引入Consumer
class Main extends Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return (
// Consumer 容器,可以拿到父组件传递下来的 fruit 属性, 以及 countUtil对象下的 addCount 和 delCount 方法
<Consumer>
{context => (
<div>
子子组件 fruit={context.fruit}
<br />
<button type="button" onClick={() => context.countUtil.addCount(2)}>
加2
</button>
<button type="button" onClick={() => context.countUtil.delCount(3)}>
减3
</button>
<hr />
</div>
)}
</Consumer>
)
}
}
export default Main