其他分享
首页 > 其他分享> > 简单的全局异步状态管理

简单的全局异步状态管理

作者:互联网

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

全局异步状态管理模块

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

  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