簡體   English   中英

反應useState鈎無法正常工作

[英]React useState hook not working as I would expect

我在React中使用useState鈎子,它的行為很奇怪。

如果您看下面的示例,這就是我的期望:調用login ,成功后調用setRefreshToken(responseToken)然后調用refresh() ,后者引用refreshToken設置的setRefreshToken 實際發生的是refreshTokenrefresh()內部未定義。

我知道setState是異步的,但是我之前從未遇到過這樣的問題。 我想念什么嗎?

import React, { createContext, useState } from "react";
import jwtDecode from "jwt-decode";

const localStorageKey = "ar_refresh_token";

export const AuthContext = createContext();

export function AuthProvider({ tokenUrl, registerUrl, refreshUrl, children }) {
  const [refreshToken, setRefreshToken] = useState(
    window.localStorage.getItem(localStorageKey)
  );

  const [accessToken, setAccessToken] = useState();

  const login = async (userId, password) => {
    const response = await fetch(tokenUrl, {
      method: "POST",
      mode: "cors",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        userId,
        password
      })
    });


    if (response.status === 201) {
      const token = await response.text();
      setRefreshToken(token);
      window.localStorage.setItem(localStorageKey, token);

      await refresh();
    }
  };

  const refresh = async () => {
    const response = await fetch(refreshUrl, {
      method: "POST",
      mode: "cors",
      headers: {
        "Content-Type": "application/json",
        Authorization: `JWT ${refreshToken}`
      }
    });


    if (response.status === 201) {
      const token = await response.text();
      setAccessToken(token);
    }
  };

  return (
    <AuthContext.Provider
      value={{
        refreshToken,
        accessToken,
        login,
        refresh
      }}
    >
      {children}
    </AuthContext.Provider>
  );
}

完整示例: https//github.com/analyticsrequired/auth-admin/blob/master/src/AuthContext.js

你是正確的,該組件將不會被重新呈現在打電話之前refresh ,所以refreshTokenrefresh將是默認的。

您可以改為從login傳遞token作為參數來refresh和使用它,它將按預期工作。

const login = async (userId, password) => {
  // ...
  if (response.status === 201) {
    // ...
    await refresh(token);
  }
};

const refresh = async refreshToken => {
  const response = await fetch(refreshUrl, {
    method: "POST",
    mode: "cors",
    headers: {
      "Content-Type": "application/json",
      Authorization: `JWT ${refreshToken}`
    }
  });

  // ...
};

每當refreshToken更改時,您可以使用useEffect自動調用refresh

...
    if (response.status === 201) {
      const token = await response.text();
      setRefreshToken(token);
      window.localStorage.setItem(localStorageKey, token);

      //await refresh();
    }
...
useEffect(
  () => {
    // your refresh code
  },
  [refreshToken]
)

useEffect內部的代碼將在第一個渲染時以及更改refreshToken之后refreshToken 因此,您無需在每次調用setRefreshToken之后都調用refresh

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM