从 Apollo 查询设置初始 React 上下文状态

Setting Initial React Context State from Apollo Query

我正在使用 React.js,特别是 Next.js,并且我有一个供用户使用的全局 React 上下文。上下文本身看起来像:

const UserContext = createContext<{
  user: User | undefined;
  setUser: (u: User | undefined) => void;
}>({
  user: undefined,
  setUser: () => {},
});

export const UserProvider = ({ children }: { children: JSX.Element }) => {
  const [user, setUser] = useState<User | undefined>(undefined);

  return (
    <UserContext.Provider value={{ user: user, setUser: setUser }}>
      {children}
    </UserContext.Provider>
  );
};

export const useUser = () => React.useContext(UserContext);

我正在我的 _app.tsx 文件中建立它,如下所示:

<UserProvider>
    <Component {...pageProps} />
</UserProvider>

但是,我想要的是在网站的初始页面加载时使用 localstorage 获取 accessToken,然后使用 Apollo Graphql 为用户查询服务器(如果他们已经登录)。为此,我尝试将以下内容添加到我的上下文提供程序中:

// in User Provider
...

  const { data, loading, error } = useQuery<{ me: UserResponse }>(MeQuery);
  const initialUser = data?.me.user;
  const [user, setUser] = useState<User | undefined>(initialUser);
...

这没有按预期工作。当我记录这个片段的输出时,它会打印两次所有内容,一次是未定义的,然后一次是查询结果的值。然而,第二次它没有被保存到状态变量中,所以当我从其他组件访问 UserContext 时,它说 User 是未定义的。如何将第二个渲染结果与来自服务器的实际数据保存在我的状态变量中?

要使 user 值与 data 保持同步,您应该在数据值更改时在 useEffect 中调用 setUser(data)

export const UserProvider = ({ children }: { children: JSX.Element }) => {
    const [user, setUser] = useState<User | undefined>(undefined);

    const { data, loading, error } = useQuery<{ me: UserResponse }>(MeQuery);
    
    useEffect(() => {
        setUser(data);
    }, [data]);

    return (
        <UserContext.Provider value={{ user: user, setUser: setUser }}>
            {children}
        </UserContext.Provider>
    );
};