ICode9

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

简单的全局异步状态管理

2022-09-09 11:00:55  阅读:177  来源: 互联网

标签:异步 stat const 状态 简单 error 全局 data useAsync


总结一下学习的成果,在不借助框架的前提下构建一个简单、完整的项目还是需要不断地学习和总结的。

全局异步状态管理模块

此模块用于管理异步请求的状态,可以实现对单个请求的状态变化跟踪,短小精悍,用来练手感觉还不错,记录一下方便以后反复回过头学习。

  1. 新建useAsync cutome hook
    import { useState } from "react";
    
    export const useAsync = () => { ... }
  2. 声明状态接口以及默认状态配置
    interface State<D> {
      data: D | null;
      stat: "idle" | "loading" | "success" | "error";
      error: Error | null;
    }
    
    const defaultInitialState: State<null> = {
      data: null,
      stat: "idle",
      error: null,
    };
    
    export const useAsync = <D>(initialState?: State<D>) => {
      const [state, setState] = useState<State<D>>({
        ...defaultInitialState,
        ...initialState,
      });
    }

    useAsync支持在创建时传入initialState用于初始化状态。

  3. 主要逻辑
    基本功能概括起来就三个:(1)运行指定的Promise;(2)设置状态;(3)传出状态。
    根据功能,创建以下函数:
    // 设置success状态
    const setData = (data: D) => {
        setState({
          data,
          stat: "success",
          error: null,
        });
      };
    
    // 设置error状态
      const setError = (error: Error) => {
        setState({
          error,
          stat: "error",
          data: null,
        });
      };
    
      const run = (promise: Promise<D>) => {
        // 判断是否是promise对象
        if (!promise || !promise.then) {
          throw new Error("请传入正确的 Promise 对象");
        }
        // 设置loading状态
        setState({ ...state, stat: "loading" });
        return promise
          .then((data) => {
            setData(data);
            return data;
          })
          .catch((err) => {
            setError(err);
            return err;
          });
      };
    
      return {
        isIdle: state.stat === "idle",
        isError: state.stat === "error",
        isSuccess: state.stat === "success",
        isLoading: state.stat === "loading",
        run,
        setData,
        setError,
        ...state,
      };

     

  4. 用法
    例如在登录页面,点击登录后的handleSubmit中:
    export const LoginScreen = () => {
      const login = (...) => { ... };
      const { run, isLoading, error } = useAsync();
    
      const handleSubmit = async (values: {
        username: string;
        password: string;
      }) => {
        await run(login(values));
      };
    
      return (
        <LongButton loading={isLoading}>登录</LongButton>
      );
    };

    首先调用useAsync(),获取run、isLoading等。run用于执行异步请求,isLoading会响应式的传出useAsync内部状态,LongButton的loading prop接收isLoading,用于判断状态。

    效果:
  5. 值得注意的地方
    需要提醒的是,useAsync中状态的变化是异步的,即promise的执行是异步的,setState也是异步的,当需要有,这同步的状态判断需求时无法使用useAsync。
    一个比较典型的例子,例如在注册页面,需要输入两次密码错误,在handleSubmit时判断是否错误,这种状态判断(或者错误判断)是同步的,因此就无法使用useAsync。

 

标签:异步,stat,const,状态,简单,error,全局,data,useAsync
来源: https://www.cnblogs.com/wananniannian/p/16671896.html

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

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

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

ICode9版权所有