我在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
将是默认组件。
您可以改为将token
从login
传递为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}`
}
});
// ...
};