Apollo Queries triggered and causing rerendering in useContext on URL Change

我怕爱的太早我们不能终老 提交于 2020-07-10 10:28:39

问题


GIF of Rerender occuring

I'm not sure how to proceed. As you can see, the Header's state (as passed down via context) is switching from the user's data --> undefined --> same user's data. This occurs every time there's a url change, and doesn't happen when I do things that don't change the url (like opening the cart for example).

Is this expected behaviour? Is there any way I can get the query in my context to only be called when there is no user data or when the user data changes? I tried using useMemo, but to no avail.

auth.context

import React, { useState} from "react";
import {
  CURRENT_USER,
  GET_LOGGED_IN_CUSTOMER,
} from "graphql/query/customer.query";
import { gql, useQuery, useLazyQuery } from "@apollo/client";
import { isBrowser } from "components/helpers/isBrowser";

export const AuthContext = React.createContext({});

export const AuthProvider = ({ children }) => {
  const [customer, { data, loading, error }] = useLazyQuery(
    GET_LOGGED_IN_CUSTOMER,
    {
      ssr: true,
    }
  );

  const { data: auth } = useQuery(CURRENT_USER, {
    onCompleted: (auth) => {
      console.log(auth);
      customer({
        variables: {
          where: {
            id: auth.currentUser.id,
          },
        },
      });
    },
    ssr: true,
  });
  console.log(data);

  const isValidToken = () => {
    if (isBrowser && data) {
      const token = localStorage.getItem("token");
      if (error) {
        console.log("error", error);
      }
      if (token && data) {
        console.log("token + auth");
        return true;
      } else return false;
    }
  };
  const [isAuthenticated, makeAuthenticated] = useState(isValidToken());
  function authenticate() {
    makeAuthenticated(isValidToken());
  }
  function signout() {
    makeAuthenticated(false);
    localStorage.removeItem("token");
  }
  return (
    <AuthContext.Provider
      value={{
        isAuthenticated,
        data,
        authenticate,
        auth,
        signout,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

(In Header, userData is equal to data just passed through an intermediary component (to provide to mobile version)). header.tsx

import React, { useContext } from "react";
import Router, { useRouter } from "next/router";
import { useApolloClient } from "@apollo/client";
import { openModal } from "@redq/reuse-modal";
import SearchBox from "components/SearchBox/SearchBox";
import { SearchContext } from "contexts/search/search.context";
import { AuthContext } from "contexts/auth/auth.context";
import LoginModal from "containers/LoginModal";
import { RightMenu } from "./Menu/RightMenu/RightMenu";
import { LeftMenu } from "./Menu/LeftMenu/LeftMenu";
import HeaderWrapper from "./Header.style";
import LogoImage from "image/hatchli-reduced-logo.svg";
import { isCategoryPage } from "../is-home-page";

type Props = {
  className?: string;
  token?: string;
  pathname?: string;
  userData?: any;
};

const Header: React.FC<Props> = ({ className, userData }) => {
  const client = useApolloClient();
  const { isAuthenticated, signout } = useContext<any>(AuthContext);
  const { state, dispatch } = useContext(SearchContext);
  console.log(isAuthenticated);
  console.log(userData);

  const { pathname, query } = useRouter();
  const handleLogout = () => {
    if (typeof window !== "undefined") {
      signout();
      client.resetStore();
      Router.push("/medicine");
    }
  };

  const handleJoin = () => {
    openModal({
      config: {
        className: "login-modal",
        disableDragging: true,
        width: "auto",
        height: "auto",
        animationFrom: { transform: "translateY(100px)" },
        animationTo: { transform: "translateY(0)" },
        transition: {
          mass: 1,
          tension: 180,
          friction: 26,
        },
      },
      component: LoginModal,
      componentProps: {},
      closeComponent: "",
      closeOnClickOutside: true,
    });
  };
  const onSearch = (text: any) => {
    dispatch({
      type: "UPDATE",
      payload: {
        ...state,
        text,
      },
    });
  };

  const { text } = state;
  const onClickHandler = () => {
    const updatedQuery = query.category
      ? { text: text, category: query.category }
      : { text };
    Router.push({
      pathname: pathname,
      query: updatedQuery,
    });
  };
  const showSearch = isCategoryPage(pathname);

  return (
    <HeaderWrapper className={className}>
      <LeftMenu logo={LogoImage} />
      {showSearch && (
        <SearchBox
          className="headerSearch"
          handleSearch={(value: any) => onSearch(value)}
          onClick={onClickHandler}
          placeholder="Search anything..."
          hideType={true}
          minimal={true}
          showSvg={true}
          style={{ width: "100%" }}
          value={text || ""}
        />
      )}
      <RightMenu
        isAuth={userData}
        onJoin={handleJoin}
        onLogout={handleLogout}
        avatar={userData && userData.user && userData.user.avatar}
      />
    </HeaderWrapper>
  );
};

export default Header;

来源:https://stackoverflow.com/questions/61895397/apollo-queries-triggered-and-causing-rerendering-in-usecontext-on-url-change

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!