使用方式
1. 创建Context
创建一个 context.js 文件,在这个 js 文件中通过 React 的 API —— React.createContext 来创建一个 Context 对象,并将这个 Context 对象导出。
// context.js
import { createContext } from 'react';
export const ThemeContext = createContext('light');
export const AuthContext = createContext(null);
React.createContext 会返回一个上下文对象 Context ,这个 Context 对象不会包含任何信息,只是提供一个表示组件上下文的对象。这个 Context 对象包含两个属性:
ThemeContext.Provider
用于包裹组件,并为被包裹的组件提供指定的 Context 的值;ThemeContext.Consumer
用于读取上下文 Context 提供的值(比较少用到)。
2. 提供 Context
在根组件 App.jsx 中,导入上面写的 ThemeContext ,并使用 ThemeContext 提供的 Provider 组件进行包裹,圈定局部的全局作用域。 Provider 组件包裹的子组件就可以读取 ThemeContext 指定的值。
import { useState } from 'react'
import { ThemeContext } from './Context.js'
import MyButton from './MyButton.jsx';
import './App.css'
function App() {
const [theme, setTheme] = useState('light');
return (
<>
<div>这是react-context-demo</div>
<div>theme: {theme}</div>
<ThemeContext.Provider value={theme}>
<MyButton></MyButton>
</ThemeContext.Provider>
</>
)
}
export default App
3. 使用 Context
在子组件中,从 React 中引入 useContext Hook 以及刚刚创建的 Context:
import { useContext } from 'react'
import { ThemeContext } from './Context.js'
import Message from './Message.jsx'
function MyButton () {
const theme = useContext(ThemeContext)
const handleChange = () => {
const newTheme = theme === 'light' ? 'dark' : 'light'
setTheme(newTheme)
}
// const handleChange = () => {}
return (
<>
<div>Button的theme是:{theme}</div>
<div>
<Message></Message>
</div>
</>
)
}
export default MyButton
4. 动态修改 Context
Context.Provider 不仅可以设置 value,也可以动态的修改 value。只需要将修改 value 的 setState 函数传入到组件 Context.Provider 的 value 中。
// App.jsx
import { useState } from 'react'
import { ThemeContext } from './Context.js'
import MyButton from './MyButton.jsx';
import './App.css'
function App() {
const [theme, setTheme] = useState('light');
return (
<>
<div>这是react-context-demo</div>
<div>theme: {theme}</div>
<ThemeContext.Provider value={{theme, setTheme}}>
<MyButton></MyButton>
</ThemeContext.Provider>
</>
)
}
export default App
// MyButton.jsx
import { useContext } from 'react'
import { ThemeContext } from './Context.js'
import Message from './Message.jsx'
function MyButton () {
const {theme, setTheme} = useContext(ThemeContext)
const handleChange = () => {
const newTheme = theme === 'light' ? 'dark' : 'light'
setTheme(newTheme)
}
// const handleChange = () => {}
return (
<>
<div>Button的theme是:{theme}</div>
<button onClick={handleChange}>change theme</button>
<div>
<Message></Message>
</div>
</>
)
}
export default MyButton
总结
- Context 的使用方式类似于CSS属性继承,无论中间层级有多深,子组件都可以获取到距离它最近的 Provider 组件提供的 value 值。
存在问题
- 一个 creatConetxt 只能创建一个全局状态,所以如果有多个全局状态,就需要多个 creatConetxt 和 Provider