首页 > 解决方案 > 使用 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”,

标签: javascriptreactjsnext.jsapollo

解决方案


推荐阅读