useContext,直译为使用上下文,作用是深层值传递,直接看例子:
components下新建一个ContextDemo.js(父子关系:ContextDemo > Demo > Child):
import React from "react";
const Demo = props => {
return <div>
<Child />
</div>
}
const Child = () => {
return (<div>Child</div>)
}
export default function ContextDemo() {
return (
<Demo />
);
}
App.js将其引入:
import { useState } from "react";
...
import ContextDemo from "./components/ContextDemo";
function App() {
....
return (
<div>
...
<ContextDemo />
</div>
);
}
export default App;
现在父级组件有个style属性,想传给孙子组件设置其背景色,可以这样一级一级地传:
import React, {useState} from "react";
const Demo = props => {
const {bgColor} = props;
return <div>
<Child bgColor={bgColor}/>
</div>
}
const Child = props => {
const style = {
backgroundColor: props.bgColor
}
return (<div style={style}>Child</div>)
}
export default function ContextDemo() {
const [bgColor] = useState("#000"); // black background color
return (
<Demo bgColor={bgColor}/>
);
}
加个换色按钮更明显:
export default function ContextDemo() {
const [bgColor, setBgColor] = useState("#000"); // black background color
return (
<div>
<button onClick={() => setBgColor("red")}>ChangeColor</button>
<Demo bgColor={bgColor} />
</div>
);
}
这样一级级传其实把代码弄得冗余了,中间一级的Demo组件只是把bgColor传给了Child组件,本身没有用到这个值。
试着拿掉Demo的bgColor,用上useContext:
import React, { useContext, useState } from "react";
const themeContext = React.createContext('');
const Demo = () => {
return <div>
<Child />
</div>
}
const Child = () => {
const bgColor = useContext(themeContext);
const style = {
backgroundColor: bgColor
}
return (<div style={style}>Child</div>)
}
export default function ContextDemo() {
const [bgColor, setBgColor] = useState("#000"); // black background color
return (
<div>
<button onClick={() => setBgColor("red")}>ChangeColor</button>
<themeContext.Provider value={bgColor}>
<Demo />
</themeContext.Provider>
</div>
);
}
createContext是创建一个上下文,后面的themeContext.Provider是生产者,"生产了"bgColor这个value,里面包含的都是它的消费者,无论多少层,要用到这个value就使用useContext来取,比如这里的Child组件。
将原来的button注释掉,来个input框换肤的特效:
{/* <button onClick={() => setBgColor("red")}>ChangeColor</button> */}
<input type="color" onChange={e => setBgColor(e.target.value)}/>
注释掉useContext,原始的消费者写法(themeContext.Consumer):
//import React, { useContext, useState } from "react";
import React, { useState } from "react";
const themeContext = React.createContext('');
const Demo = () => {
return <div>
<Child />
</div>
}
const Child = () => {
// const bgColor = useContext(themeContext);
// const style = {
// backgroundColor: bgColor
// }
// return (<div style={style}>Child</div>)
return <themeContext.Consumer>
{value => <div style={{ backgroundColor: value }}>Child</div>}
</themeContext.Consumer>
}
export default function ContextDemo() {
const [bgColor, setBgColor] = useState("#000"); // black background color
return (
<div>
{/* <button onClick={() => setBgColor("red")}>ChangeColor</button> */}
<input type="color" onChange={e => setBgColor(e.target.value)} />
<themeContext.Provider value={bgColor}>
<Demo />
</themeContext.Provider>
</div>
);
}