一、前言
在《React 之 Context API(一)》中,最后一个例子给出了一个全局Context,其Provider包裹在顶层,Consumer分散至其它组件中“各取所需”。
当然,React的Context API肯定不是想让大家都这么使用,否则那还不如直接使用Redux!
本篇,将带给大家一个全新的例子,正如标题所示,多个Context!既然有多个Context,肯定就有与之对应的多个Provider,至于Consumer可以随意多个,但是,来自同一个Context的Consumer必需在同一个Context的Provider之内才行(上篇2.3节第3点)。
二、Case之UI架构图
该Demo咋一看比较复杂,实际就5个组件:
- 最外层是<App/>
- 次外层是<ParentA/>,<ParentB/>
- ParentA中含有<ChildA/>,ParentB中含有<ChildB/>
三、Case实现
3.1、前提准备
import React from 'react';
import ReactDOM from 'react-dom';
const GlobalContext = React.createContext();
const ContextA = React.createContext();
const ContextB = React.createContext();
// 随机生成数字
const randomNumber = (def = 100) => Math.floor(Math.random() * def);
// 随机生成颜色
const bgColor = () => {
let color = '#';
[0, 1, 2].forEach(() => {
const c = randomNumber();
color += (c < 10 ? `0${c}` : c);
});
return color;
};
ReactDOM.render(
<React.StrictMode>
<App/>
</React.StrictMode>,
document.getElementById('root')
);
3.2、App组件
function App() {
const [params, setParams] = React.useState([
{
studentId: randomNumber(10000),
name: 'chris-' + randomNumber(10000),
age: randomNumber()
}
]);
const addStudent = () => {
setParams([
...params,
{
studentId: randomNumber(10000),
name: 'chris-' + randomNumber(10000),
age: randomNumber()
}
]);
};
return (
<GlobalContext.Provider value={params}>
<div style={{backgroundColor: bgColor()}}>
<div onClick={addStudent} style={{backgroundColor: bgColor()}}>addStudent</div>
<br/>
<ParentA/>
<br/>
<ParentB/>
</div>
</GlobalContext.Provider>
);
}
3.3、ParentA组件和ChildA组件
function ParentA() {
const [name, setName] = React.useState("chris-" + randomNumber());
return (
<ContextA.Provider value={name}>
<div style={{backgroundColor: bgColor()}}>
<div onClick={() => setName('chris-' + randomNumber())}>ParentA</div>
<ChildA/>
</div>
</ContextA.Provider>
);
}
function ChildA() {
return (
<ContextA.Consumer>
{(name) => <div>{`ContextA.Consumer => ***name = ${name}***`}</div>}
</ContextA.Consumer>
);
}
3.4、ParentB组件
function ParentB() {
const [age, setAge] = React.useState(randomNumber());
return (
<ContextB.Provider value={age}>
<div style={{backgroundColor: bgColor()}}>
<div onClick={() => setAge(randomNumber())}>ParentB</div>
<ChildB/>
</div>
</ContextB.Provider>
);
}
3.5、ChildB组件
function ChildB() {
const renderGlobalConsumer = (students) => {
const s = students.map(
(student, idx) =>
<div key={idx}>
studentId: {student.studentId} / name: {student.name} / age = {student.age}
</div>
);
return (
<div style={{backgroundColor: bgColor()}}>
<div>GlobalContext.Consumer => students.length = {students.length}</div>
{s}
</div>
);
};
return (
<GlobalContext.Consumer>
{(students) =>
<ContextB.Consumer>
{(age) =>
<div>
<div>{`ContextB.Consumer => ***age = ${age}***`}</div>
<br/>
{renderGlobalConsumer(students)}
</div>
}
</ContextB.Consumer>
}
</GlobalContext.Consumer>
);
}
3.6、执行效果
点击“addStudent”后的结果(变色是因为每次都调用bgColor方法拿新的背景色):