Context(类似 Vue 的 provide/inject,适合中等规模)
// 创建 Context
const ThemeContext = React.createContext<'light' | 'dark'>('light');
// 提供者
function App() {
const [theme, setTheme] = useState<'light'|'dark'>('light');
return (
<ThemeContext.Provider value={theme}>
<Toolbar />
</ThemeContext.Provider>
);
}
// 消费者(在任意子组件)
function Toolbar() {
const theme = useContext(ThemeContext);
return <div>Current theme: {theme}</div>;
}
详细介绍一下context 使用方法
第一步:将 Context 定义在一个单独的文件(或至少导出)
// contexts/ThemeContext.tsx
import { createContext } from 'react';
export const ThemeContext = createContext<'light' | 'dark'>('light');
第二步:在 App 中导入 Provider 并包裹路由
// App.tsx
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import { ThemeContext } from './contexts/ThemeContext';
import Home from './pages/home';
import About from './pages/About';
import UserDetail from './pages/userDetail';
function App() {
const [theme, setTheme] = useState<'light'|'dark'>('light');
return (
<BrowserRouter>
<ThemeContext.Provider value={theme}>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/user/:id" element={<UserDetail />} />
</Routes>
</ThemeContext.Provider>
</BrowserRouter>
);
}
第三步:在任意路由组件中导入并使用同一个 Context
// pages/home.tsx
import { useContext } from 'react';
import { ThemeContext } from '../contexts/ThemeContext';
export default function Home() {
const theme = useContext(ThemeContext);
return <div>Home - current theme: {theme}</div>;
}
// pages/userDetail.tsx
import { useContext } from 'react';
import { useParams } from 'react-router-dom';
import { ThemeContext } from '../contexts/ThemeContext';
export default function UserDetail() {
const { id } = useParams();
const theme = useContext(ThemeContext);
return (
<div>
User ID: {id} <br />
Theme: {theme}
</div>
);
}
常见错误与检查清单
| 错误现象 | 可能原因 | 解决方法 |
|---|---|---|
useContext(ThemeContext) 返回默认值 'light',修改 Provider 的 value 也没用 |
你在组件中导入的 ThemeContext 和 Provider 使用的不是同一个对象(比如从不同文件导出了两个不同的 Context) |
确保整个应用只定义一次 createContext,并且所有地方都从同一个文件导入 |
报错 ThemeContext is not defined |
没有导入 Context | 在需要使用 useContext 的文件里 import { ThemeContext } from '...' |
| Context 值变化了,但某些路由组件没有更新 | 可能是路由组件被 React.memo 包裹,或者你在 Provider 外面使用了 BrowserRouter 导致 Context 没有包裹到该路由 |
把 ThemeContext.Provider 放在 BrowserRouter 内部 (但包裹住 Routes 就行,你原来的位置是对的) |
在 UserDetail 组件中 useParams() 拿不到 id |
路由配置错误:<Route path="/user/:id" element={<UserDetail />} /> 必须正确,且 UserDetail 必须是在 <Routes> 内渲染的组件,不能是嵌套在 App 内部的函数 |
将 UserDetail 提取为单独的文件或至少定义在 App 外部 |
总结
-
Context 在路由组件 ,只要 Provider 包裹了
<Routes>。 -
关键点:同一个 Context 对象必须被所有使用它的组件导入。
-
如果你按文件拆分,记得
export和import。