React项目 鉴权功能
场景:
- 有的页面需要用户先登录才可以访问
- 有的功能需要用户先登录才可以使用
- 有的功能需要确认用户是否拥有权限
如果有redux,其实把鉴权信息放在redux就可以,如果项目没有使用redux,那么就可以通过以下方式实现
实现原理:
- 创建一个
context,context.Provider向下注入的值是一个包含 响应性的state+修改state的方法 的对象,并在根组件向下注入,这样,下面的组件随时可以调用useContext获取上述对象,进而实现全局同步鉴权信息
实现步骤
-
创建
auth context在
src/contexts/authContext.js文件中// 鉴权context import { createContext } from "react"; const auth = createContext(); export default auth; -
书写鉴权功能
在
src/utils/useProvideAuth.js文件中import { useState } from "react" // 提供鉴权功能 const useProvideAuth = () => { // auth为true,代表已登录、已鉴权。默认为未鉴权 const [auth, setAuth] = useState(false); // 更新鉴权 const updateAuth = (newState, cb) => { setAuth(newState); cb && cb(); } return { auth, updateAuth } } export default useProvideAuth; -
创建提供鉴权的组件
其实如果 根组件
App是用function Component函数式组件创建的话,可以不需要这步,直接在 根组件 中Provider,因为我们当前项目是class Component类组件,不可以使用useState Hooks,所以我们要再创建一个 函数式组件进行注入。在
src/utils/AuthProvider.jsx中// 提供鉴权的组件 import React from "react"; // 导入 鉴权功能 import useProvideAuth from "./useProvideAuth"; // 导入 鉴权Context import auth from "../contexts/authContext" function AuthProvider({ children }) { return ( <auth.Provider value={useProvideAuth()}> {children} </auth.Provider> ) } export default AuthProvider; -
在
main.jsx中,给根组件包裹AuthProviderimport React from 'react' import ReactDOM from 'react-dom' .... // 引入根组件 import App from './App'; // 导入路由 import { HashRouter } from "react-router-dom"; // 导入鉴权组件 import AuthProvider from "./utils/AuthProvider.jsx" ReactDOM.render( <AuthProvider> <HashRouter> <App></App> </HashRouter> </AuthProvider> , document.getElementById('root') ) -
在遇到需要鉴权功能时:
使用
useContext获取鉴权功能,进行使用/** * 找房页面 * * FindHouse */ import React, { useContext } from "react"; import { Button, Toast } from "antd-mobile"; // 导入鉴权Context import authContext from "@/contexts/authContext" function FindHouse() { // 获取 鉴权功能 const auth = useContext(authContext); // 需要登录的操作 const operationNeedLogin = () => { // 判断是否鉴权 if (!auth.auth) { return Toast.show("需要登录才可以"); } Toast.show("可以操作") } return ( <div> <h3>找房页面</h3> {/* 需要登录的操作 */} <Button type="ghost" onClick={operationNeedLogin}>需要登录的操作</Button> </div> ) } export default FindHouse; -
再遇到需要鉴权才能访问的页面时
import React, { useContext } from "react" import authProvider from "@/contexts/authContext"; import { Redirect } from "react-router"; // 一个需要登录才能访问的页面 function News(props) { const auth = useContext(authProvider); return ( // 是否鉴权,未登录跳转到登录页 auth.auth ? <div> <h2>News</h2> <p>假设这是一个需要登录才可以访问的页面</p> </div> : <Redirect to="/login"></Redirect> ) } export default News;
总结
- 其实完成这个功能的思想,不只可以用于 全局鉴权,这个思想 本质上就是全局通信的一种实现。