我不确定如何继续。如您所见,Header的状态(通过上下文向下传递)正在从用户数据->未定义->同一用户的数据中切换。每次更改网址时都会发生这种情况,当我执行不更改网址的操作时(例如打开购物车),这种情况就不会发生。
这是预期的行为吗?有什么方法可以让我的上下文中的查询仅在没有用户数据或用户数据更改时才被调用?我尝试使用useMemo,但无济于事。
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>
);
};
(在标头中,userData
等于刚刚通过中间组件传递(提供给移动版本)的data
)。
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;