javascript - 使用 Apollo + useContext 进行不必要的重新渲染以进行身份验证 (SSR)
问题描述
当我不希望它被调用时,我似乎正在经历重新渲染。useQuery
首先加载,isAuthenticated
的状态通过一个函数实例化,该函数向服务器查询以根据附加的标头获取 userId。如果存在有效的标头,isAuthenticated
则设置为 true 并因此useMemo
被调用(作为isAuthenticated
依赖项)。useMemo
调用setUser
,将 userId 和角色放入上下文中,通过 AuthProvider 向下传递(在 中_app
,包装除了 ApolloProvider 之外的所有内容)。
我使用导航栏中的 userId(通过useContext
)来获取头像(以及应用程序其余部分中的其他内容)。我注意到的是,每当我点击某个东西(例如,一个单独的查询过滤产品)时,都会调用CURRENT_USER
查询。_app
这表现为导航栏丢失传递给它的 useId 数据一秒钟,然后恢复。所以,每次我点击东西时,我的导航栏都会重新渲染。我不明白为什么CURRENT_USER
查询一直被调用......
对于上下文,我在另一个没有 SSR 的应用程序中使用相同的设置。
auth.context.js
import React, { useState, useEffect, useMemo} from "react";
import { CURRENT_USER } from "graphql/query/customer.query";
import { gql, useQuery } from "@apollo/client";
import { isBrowser } from "components/helpers/isBrowser";
export const AuthContext = React.createContext({});
export const AuthProvider = ({ children }) => {
const { data, error, loading } = useQuery(CURRENT_USER, {
onCompleted: () => {
console.log("called query", data);
},
ssr: true,
});
const isValidToken = () => {
if (isBrowser) {
const token = localStorage.getItem("token");
if (error) {
return false;
}
if (!loading && !data) {
return false;
}
if (token && data?.currentUser) {
console.log(data.currentUser);
return true;
}
if (!token) {
return false;
}
}
};
const [isAuthenticated, makeAuthenticated] = useState(isValidToken());
const [user, setUser] = useState({});
function authenticate() {
console.log(isAuthenticated);
makeAuthenticated(isValidToken());
}
useEffect(() => {
console.log("attempted to run");
if (data && isAuthenticated) {
setUser(data.currentUser);
console.log("user", user);
}
}, [isAuthenticated]);
function signout() {
makeAuthenticated(false);
localStorage.removeItem("token");
}
return (
<AuthContext.Provider
value={{
isAuthenticated,
authenticate,
signout,
user,
}}
>
{children}
</AuthContext.Provider>
);
};
"@apollo/client": "^3.0.0-beta.44",
"下一个": "^9.3.6",
“反应”:“^16.13.1”,
解决方案
推荐阅读
- javascript - 更改包含对象数组的对象中的属性名称
- postgresql - DBeaver localhost PostgreSQL 连接被拒绝
- angular - 如何在角度中使用 ag-grid 的 headerClass 属性?
- javascript - 谷歌 Appscript WebApp 刷新
- javascript - Three.js 和 gsap 缩放动画
- python - 使用 Scopus API 检索特定作者的摘要?
- html - 在 sass 中使用 map、list 和 for 循环更改元素的字体大小
- oracle - OracleJDBC 驱动程序和 Tomcat java.sql.SQLException:没有合适的驱动程序
- php - 如何在将标签保留在 PHP (preg_replace) 中的同时替换 HTML 标签内的空格?
- azure-functions - Azure 计时器触发功能根本不执行脚本日志