我已经创建了一个钩子useToken,它跟踪和更新我的访问和刷新令牌的状态.

当应用程序启动时,令牌将从本地存储中提取并刷新,以更新挂钩状态的值以及本地存储中的值.

本地存储中的值按预期更新,但状态的值不反映更改.我知道setState是异步的,但即使在等待或使用时也是如此.则()状态不会更新.

在使用令牌的下方可以注意到这一点,并且请求失败,因为访问令牌不匹配.

/hooks/useTokens.tsx:

import { useState } from "react";

export default function useTokens() {
  const [tokens, setTokensState] = useState({
    apiToken: localStorage.getItem("apiToken"),
    refreshToken: localStorage.getItem("refreshToken"),
  });

  const setTokens = (tokenParams: {
    apiToken: string | null;
    refreshToken: string | null;
  }) => {
    const newTokens = { ...tokens, ...tokenParams };
    setTokensState(newTokens);
    newTokens.apiToken
      ? localStorage.setItem("apiToken", newTokens.apiToken)
      : localStorage.removeItem("apiToken");
    newTokens.refreshToken
      ? localStorage.setItem("refreshToken", newTokens.refreshToken)
      : localStorage.removeItem("refreshToken");
  };

  return { tokens, setTokens };
};

home.tsx个个

const { tokens, setTokens } = useTokens();
...
      refreshToken(tokens.refreshToken!).then(
        ({ isSuccessful, data, status }) => {
          if (isSuccessful) {
            // data.access_token contains new token
            // tokens.xyz contains old access/refresh token even after setTokens
            setTokens({
              apiToken: data.access_token,
              refreshToken: data.refresh_token,
            });
            accountsAndAuthCheck();
          } else {
            console.log("refresh", data, status);
            setTokens({ apiToken: null, refreshToken: null });
            navigate("/link", { replace: true });
          }
        }
      );

home.tsx个个

...
const accountsAndAuthCheck = () => {

    // tokens.apiToken has not updated
    getAccounts(tokens.apiToken!).then(({ isSuccessful, data, status }) => {
      if (isSuccessful) {
        setIsAuthorised(1);
        const _accountId = data.accounts[0].id;
        setAccountId(_accountId);
      } else {
        if (status == 403) {
          setIsAuthorised(-1);
        }
      }
    });
  };
...

推荐答案

如果您希望在不使用自定义挂钩状态情况下修复此问题,我会将Token作为参数传递给accountsAndAuthCheck函数,并在挂钩中仅设置本地存储

/hooks/useTokens.tsx:

export default function useTokens() {

  const setTokens = (tokenParams: {
    apiToken: string | null;
    refreshToken: string | null;
  }) => {
    const newTokens = {...tokenParams };
    newTokens.apiToken
      ? localStorage.setItem("apiToken", newTokens.apiToken)
      : localStorage.removeItem("apiToken");
    newTokens.refreshToken
      ? localStorage.setItem("refreshToken", newTokens.refreshToken)
      : localStorage.removeItem("refreshToken");
  };

  return { setTokens };
};



home.tsx

const { tokens, setTokens } = useTokens();

      refreshToken(tokens.refreshToken!).then(
        ({ isSuccessful, data, status }) => {
          if (isSuccessful) {
            setTokens({
              apiToken: data.access_token,
              refreshToken: data.refresh_token,
            });
            accountsAndAuthCheck(data.access_token, data.refresh_token);
          } else {
            console.log("refresh", data, status);
            setTokens({ apiToken: null, refreshToken: null });
            navigate("/link", { replace: true });
          }
        }
      );


const accountsAndAuthCheck = (apiToken, refreshToken) => {

    getAccounts(apiToken!).then(({ isSuccessful, data, status }) => {
      if (isSuccessful) {
        setIsAuthorised(1);
        const _accountId = data.accounts[0].id;
        setAccountId(_accountId);
      } else {
        if (status == 403) {
          setIsAuthorised(-1);
        }
      }
    });
  };

如果您想在您自定义钩子中保留状态,我建议您try 在useEffect中更改token状态来触发accountsAndAuthCheck功能

Typescript相关问答推荐

如何在类型脚本中声明对象其键名称不同但类型相同?

根据另一个成员推断类成员的类型

如何在方法中定义TypeScript返回类型,以根据参数化类型推断变量的存在?

typescript抱怨值可以是未定义的,尽管类型没有定义

属性的类型,该属性是类的键,其值是所需类型

如何使用泛型自动推断TS中的类型

TypeScrip 5.3和5.4-对`Readonly<;[...number[],字符串]>;`的测试版处理:有什么变化?

Angular 15使用react 式表单在数组内部创建动态表单数组

如何在深度嵌套的Reaction路由对象中隐藏父级?

如何在Typescript 中组合unions ?

如何 bootstrap TS编译器为类型化属性`T`推断正确的类型?

刷新页面时,TypeScrip Redux丢失状态

保护函数调用,以便深度嵌套的对象具有必须与同级属性函数cargument的类型匹配的键

判断映射类型内的键值的条件类型

->;Boolean类型的键不能分配给类型Never

从route.参数获取值.订阅提供";无法读取未定义";的属性

当数组类型被扩展并提供标准数组时,TypeScrip不会抱怨

如何在TypeScrip中使用数组作为字符串的封闭列表?

有没有一种方法可以防止我的组件包在其中安装样式组件'; node 模块中的s目录

如何根据Typescript 中带有泛型的对象嵌套键数组获取数组或对象的正确类型?