useContext
是 React 的一个 Hook,用来 在组件树中共享全局数据,避免 props 一层层传递。应用场景有,全局主题(深色 / 浅色)、用户信息(登录状态)、多语言(i18n),配置项、权限控制等。
一. 基本使用步骤
1、创建 context
javascript
复制代码
js
复制编辑
import { createContext } from 'react';
const ThemeContext = createContext('light'); // 默认值是 'light'
2、使用 Provider 提供数据
xml
复制代码
jsx
复制编辑
<ThemeContext.Provider value="dark">
<App />
</ThemeContext.Provider>
3、在子组件中使用 useContext 获取数据
javascript
复制代码
jsx
复制编辑
import { useContext } from 'react';
const MyComponent = () => {
const theme = useContext(ThemeContext);
return <div>当前主题:{theme}</div>;
};
二、完整示例
javascript
复制代码
jsx
复制编辑
// ThemeContext.js
import { createContext } from 'react';
export const ThemeContext = createContext('light');
javascript
复制代码
jsx
复制编辑
// App.js
import React from 'react';
import { ThemeContext } from './ThemeContext';
import Page from './Page';
export default function App() {
return (
<ThemeContext.Provider value="dark">
<Page />
</ThemeContext.Provider>
);
}
javascript
复制代码
jsx
复制编辑
// Page.js
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
export default function Page() {
const theme = useContext(ThemeContext);
return <div>当前主题是:{theme}</div>;
}
三、补充说明:
特性 |
说明 |
createContext() |
创建一个 context 对象 |
Provider |
包裹需要共享的组件树,传入 value |
useContext(context) |
读取 context 的值 |
默认值 |
如果没有 Provider,读取的是 createContext 的默认值 |
四、使用场景
1、按钮权限控制:
第一步:创建权限上下文
javascript
复制代码
js
复制编辑
// AuthContext.js
import { createContext } from 'react';
export const AuthContext = createContext({
permissions: [], // 权限列表,比如 ['view', 'edit']
});
第二步:创建 AuthProvider 提供权限
javascript
复制代码
jsx
复制编辑
// AuthProvider.js
import React from 'react';
import { AuthContext } from './AuthContext';
// 模拟从后端接口拿到的权限
const mockPermissions = ['view', 'edit'];
export default function AuthProvider({ children }) {
return (
<AuthContext.Provider value={{ permissions: mockPermissions }}>
{children}
</AuthContext.Provider>
);
}
第三步:封装一个权限组件 <HasPermission>
javascript
复制代码
jsx
复制编辑
// HasPermission.js
import React, { useContext } from 'react';
import { AuthContext } from './AuthContext';
export default function HasPermission({ children, value }) {
const { permissions } = useContext(AuthContext);
if (permissions.includes(value)) {
return <>{children}</>;
}
return null;
}
第四步:在主入口使用 AuthProvider
javascript
复制代码
jsx
复制编辑
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import AuthProvider from './AuthProvider';
ReactDOM.render(
<AuthProvider>
<App />
</AuthProvider>,
document.getElementById('root')
);
第五步:使用权限组件控制显示内容
javascript
复制代码
jsx
复制编辑
// App.js
import React from 'react';
import HasPermission from './HasPermission';
function App() {
return (
<div>
<h1>操作区</h1>
<HasPermission value="edit">
<button>编辑</button>
</HasPermission>
<HasPermission value="delete">
<button>删除</button> {/* 没权限时不会显示 */}
</HasPermission>
</div>
);
}
export default App;
第五步: 总结思路
功能 |
说明 |
动态获取权限 |
从登录接口返回后设置权限列表 |
多权限判断 |
value={['edit', 'delete']} (自己扩展支持数组) |
权限 hooks |
可以封装 useHasPermission() 简化组件调用 |
配合路由守卫 |
可以结合 react-router 控制页面访问 |
2、菜单权限控制:
第一步:菜单定义
arduino
复制代码
js
复制编辑
// menus.js
export const menus = [
{ label: '首页', path: '/', permission: 'view_home' },
{ label: '用户管理', path: '/user', permission: 'manage_user' },
{ label: '设置', path: '/settings', permission: 'view_settings' },
];
第二步:用户权限上下文
javascript
复制代码
js
复制编辑
// AuthContext.js
import { createContext } from 'react';
export const AuthContext = createContext({
permissions: [],
});
javascript
复制代码
js
复制编辑
// AuthProvider.js
import React from 'react';
import { AuthContext } from './AuthContext';
const userPermissions = ['view_home', 'view_settings']; // 示例权限
export default function AuthProvider({ children }) {
return (
<AuthContext.Provider value={{ permissions: userPermissions }}>
{children}
</AuthContext.Provider>
);
}
第三步:菜单组件(根据权限过滤)
javascript
复制代码
jsx
复制编辑
// MenuList.js
import React, { useContext } from 'react';
import { AuthContext } from './AuthContext';
import { menus } from './menus';
export default function MenuList() {
const { permissions } = useContext(AuthContext);
const allowedMenus = menus.filter(menu =>
permissions.includes(menu.permission)
);
return (
<ul>
{allowedMenus.map(menu => (
<li key={menu.path}>{menu.label}</li>
))}
</ul>
);
}
第四步:使用菜单组件
javascript
复制代码
jsx
复制编辑
// App.js
import React from 'react';
import MenuList from './MenuList';
function App() {
return (
<div>
<h2>菜单</h2>
<MenuList />
</div>
);
}
export default App;
第五步: 总结思路
优化点 |
说明 |
动态菜单来自接口 |
支持服务端返回权限和菜单配置 |
多级菜单 |
递归判断子菜单权限 |
UI 框架集成 |
可配合 Ant Design Vue、Element Plus 做出侧边栏 |
高亮路由 |
与 react-router 结合加 NavLink |