使用React Context全局注入用户认证信息
作者:互联网
继续记录自己学习React的心得
React Context
Context的功能简单地说就是可以将一些数据注入到Context对象中,使其下辖的组件可以随时随地访问这些数据,省去了逐层传递的步骤。
相对于在组件里挖槽(比如{props.children}),使用Context应该更注重随时随地都可能有需求使用这些数据这个目的。
用到的两个核心API:
- React.createContext(defaultValue)
创建Context对象,可传入defaultValue或undefined。defaultValue的作用官网有介绍,即:当某个组件订阅了Context但未匹配到Provider时,就会访问defaultValue值,当传入undefined时,defaultValue无效。 - Context.Provider
Context对象都会返回Provider组件,其下的组件会订阅Provider中的数据。Provider接收value属性,用于将value传递给消费组件,当value发生变化时所有消费组件都会重新渲染。
使用React Context全局注入用户认证信息
内容衔接之前的用户认证模块。首先需要明确为何需要全局注入用户认证信息,其实一个最简单的答案就是:之前的用户认证模块只提供了用户认证的方法,并没有提供存储用户认证信息的功能,而用户认证信息又是一个大部分组件都有可能使用的数据,所以将其注入到Context中是很有意义的。
目前所构建的用户认证模块大致包括下列内容:
// User接口 export interface User { id: string; name: string; email: string; title: string; organization: string; token: string; } // 获取token export const getToken = () => { ... }; // 登录 export const login = (param) => { ... }; // 注册 export const register = (param) => { ... }; // 登出 export const logout = () => { ... };
下面开始构建AuthContext模块:
该模块包括三大内容:Context对象创建、Provider组件构建、useContext Hook调用。
Context对象需要传入用户认证模块所有的必要数据和方法,如下
const AuthContext = React.createContext< | { user: User | null; login: (form: AuthForm) => Promise<void>; register: (form: AuthForm) => Promise<void>; logout: () => Promise<void>; } | undefined >(undefined); // 更改Context名称 AuthContext.displayName = "AuthContext";
注意login、register、logout返回的都是fetch()
Provider组件构建涉及到用户认证信息初始化、异步请求状态管理。
用户认证信息初始化主要是需要读取token,用以保持用户登录状态,如下
import * as auth from "用户认证模块"; const boostrapUser = async () => { let user = null; const token = auth.getToken(); if (token) { const data = await fetch(...) // 验证用户身份 user = data.user; } return user; };
请求状态管理主要是将异步请求状态管理和Provider结合,如下
const { data: user, error, run, isIdle, isError, isLoading, setData: setUser, } = useAsync<User | null>(); // 重写用户认证模块的几个函数,将其与异步请求管理相结合 const login = (form: AuthForm) => auth.login(form).then(setUser); const register = (form: AuthForm) => auth.register(form).then(setUser); const logout = () => auth.logout().then(() => setUser(null)); // Provider初次渲染时先初始化用户认证信息 useEffect(() => { run(boostrapUser()); }, []);
// isLoading, isIdle, isError可用于呈现Provider组件不同状态
return (
<AuthContext.Provider
children={children}
value={{ user, login, register, logout }} // 传入Context所需的value
/>
);
useContext Hook的便是提供给其他组件访问Provider属性的一个简单方法,用法如下
export const useAuth = () => { const context = React.useContext(AuthContext); if (!context) { // 必须保证context对象存在 throw new Error("useAuth必须在AuthProvider中使用"); } return context; };
AuthProvider用法
举例在login页面的简单用法:
export const LoginScreen = () => { const { user, login } = useAuth(); const { run, isLoading, error } = useAsync(); const handleSubmit = async (values: { username: string; password: string; }) => { await run(login(values)); // 可全局调用login }; return ( <Form onFinish={handleSubmit}> {user ? ( // 全局读取user,且状态都是一致的 登录成功,用户:{user?.name} ) : null} ...... <Form.Item> <LongButton loading={isLoading} htmlType={"submit"} type={"primary"}> 登录 </LongButton> </Form.Item> </Form> ); };
标签:const,用户,认证,React,user,Context,Provider 来源: https://www.cnblogs.com/wananniannian/p/16691788.html