[英]React useState hook not working as I would expect
我在React中使用useState
鈎子,它的行為很奇怪。
如果您看下面的示例,這就是我的期望:調用login
,成功后調用setRefreshToken(responseToken)
然后調用refresh()
,后者引用refreshToken
設置的setRefreshToken
。 實際發生的是refreshToken
在refresh()
內部未定義。
我知道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
,所以refreshToken
內refresh
將是默認的。
您可以改為從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.