在页面呈现之前使用 fetch 设置状态
Using fetch to set state before the page renders
我正在为 React 组件构建守卫。警卫获取 Auth0 JWT 并检查我们的 API 以查看该用户是否存在于我们的数据库中。如果用户确实存在,我们将 userExists
设置为 true
并将他们重定向到 /dashboard
。如果用户不存在,我们调用postUser
并将它们发送到/complete-profile
。
我 运行 遇到的问题是页面在 userExists
被 fetch 调用正确设置之前呈现。换句话说,如果我要 运行 下面的代码,日志将按以下顺序读取:
- 用户确实存在
- 提取调用 1
const SomeGuard: FC<SomeGuardProps> = ({ children }) => {
const { isAuthenticated } = useAuth();
const isMountedRef = useIsMountedRef();
const [userExists, setUserExists] = React.useState(true);
const getUser = useCallback( async () => {
try {
var user_exists;
fetch(`https://website.com/user`,
{
headers: {
Authorization: `Bearer DFJKS54DUJ6DD.SDF2KJWEF4NKN3JKw4534.DFSKJ5HSKDJ6HF`,
},
method: 'GET',
},
).then(response => {
if (response.status===200) { // USER EXISTS
console.log("FETCH CALLED 1")
setUserExists(true);
}
else if (response.status===404) { // catch 404 -- USER NOT FOUND
console.log("FETCH CALLED 2")
setUserExists(false);
}
return response.json();
})
}
catch (e) {
console.error(e);
}
}, [isMountedRef]);
const postUser = useCallback( async () => {
// assume this works and sends a POST request to our API
// to create a user
)}
useEffect(() => {
console.log("STEP 1");
getUser();
}, [getUser]);
if (isAuthenticated) {
if (!userExists) {
console.log("USER DOES NOT EXIST");
postUser();
return <Redirect to="/complete-profile" />;
}
else if (userExists) {
console.log("USER DOES EXIST");
return <Redirect to="/dashboard" />;
}
}
if (!isAuthenticated) {
console.log("TRIED TO HIT DASHBOARD WITHOUT BEING LOGGED IN");
return <Redirect to="/login" />;
}
return (
<>
{children}
</>
);
};
SomeGuard.propTypes = {
children: PropTypes.node
};
export default SomeGuard;
因为它在调用 fetch
之前呈现页面,所以我最初设置 userExists
的值始终决定呈现哪个页面。
请帮忙!我在这里错过了什么?如何在页面呈现之前调用 fetch
更新 userExists
?
将 userExists
的初始值设置为其他值,例如 null
,这样您就可以区分未加载的页面和已加载的真实/已加载和错误的页面。然后,只渲染一次 userExists
不为空:
const [userExists, setUserExists] = React.useState(null);
if (isAuthenticated) {
if (userExists === false) {
console.log("USER DOES NOT EXIST");
postUser();
return <Redirect to="/complete-profile" />;
}
else if (userExists === true) {
console.log("USER DOES EXIST");
return <Redirect to="/dashboard" />;
}
}
return userExists === null ? null : children;
我正在为 React 组件构建守卫。警卫获取 Auth0 JWT 并检查我们的 API 以查看该用户是否存在于我们的数据库中。如果用户确实存在,我们将 userExists
设置为 true
并将他们重定向到 /dashboard
。如果用户不存在,我们调用postUser
并将它们发送到/complete-profile
。
我 运行 遇到的问题是页面在 userExists
被 fetch 调用正确设置之前呈现。换句话说,如果我要 运行 下面的代码,日志将按以下顺序读取:
- 用户确实存在
- 提取调用 1
const SomeGuard: FC<SomeGuardProps> = ({ children }) => {
const { isAuthenticated } = useAuth();
const isMountedRef = useIsMountedRef();
const [userExists, setUserExists] = React.useState(true);
const getUser = useCallback( async () => {
try {
var user_exists;
fetch(`https://website.com/user`,
{
headers: {
Authorization: `Bearer DFJKS54DUJ6DD.SDF2KJWEF4NKN3JKw4534.DFSKJ5HSKDJ6HF`,
},
method: 'GET',
},
).then(response => {
if (response.status===200) { // USER EXISTS
console.log("FETCH CALLED 1")
setUserExists(true);
}
else if (response.status===404) { // catch 404 -- USER NOT FOUND
console.log("FETCH CALLED 2")
setUserExists(false);
}
return response.json();
})
}
catch (e) {
console.error(e);
}
}, [isMountedRef]);
const postUser = useCallback( async () => {
// assume this works and sends a POST request to our API
// to create a user
)}
useEffect(() => {
console.log("STEP 1");
getUser();
}, [getUser]);
if (isAuthenticated) {
if (!userExists) {
console.log("USER DOES NOT EXIST");
postUser();
return <Redirect to="/complete-profile" />;
}
else if (userExists) {
console.log("USER DOES EXIST");
return <Redirect to="/dashboard" />;
}
}
if (!isAuthenticated) {
console.log("TRIED TO HIT DASHBOARD WITHOUT BEING LOGGED IN");
return <Redirect to="/login" />;
}
return (
<>
{children}
</>
);
};
SomeGuard.propTypes = {
children: PropTypes.node
};
export default SomeGuard;
因为它在调用 fetch
之前呈现页面,所以我最初设置 userExists
的值始终决定呈现哪个页面。
请帮忙!我在这里错过了什么?如何在页面呈现之前调用 fetch
更新 userExists
?
将 userExists
的初始值设置为其他值,例如 null
,这样您就可以区分未加载的页面和已加载的真实/已加载和错误的页面。然后,只渲染一次 userExists
不为空:
const [userExists, setUserExists] = React.useState(null);
if (isAuthenticated) {
if (userExists === false) {
console.log("USER DOES NOT EXIST");
postUser();
return <Redirect to="/complete-profile" />;
}
else if (userExists === true) {
console.log("USER DOES EXIST");
return <Redirect to="/dashboard" />;
}
}
return userExists === null ? null : children;