ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用React Context全局注入用户认证信息

2022-09-14 10:00:58  阅读:312  来源: 互联网

标签:const 用户 认证 React user Context Provider


继续记录自己学习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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有