Hook requires data from another hook, but getting Error: Rendered more hooks than during the previous render

Hook requires data from another hook, but getting Error: Rendered more hooks than during the previous render

我遇到错误:

Rendered more hooks than during the previous render.

我找到了一些答案,说我应该将所有挂钩调用放在顶部。

但是,在下面的代码中,session 在加载时打印 undefined 3 次,直到它第四次打印 session 对象。

因此,我添加了对 loading 状态的检查。

import { signIn, signOut, useSession } from "next-auth/client";
import { request } from "graphql-request";
import useSWR from "swr";

export default function Profile() {
  const [session, loading] = useSession();

  if (loading) {
    return <p className="">loading...</p>;
  }
  if (!session) {
    signIn();
  }

  const { data: user } = useSWR([USER_QUERY, session.email], (query, email) =>
    request("/api/graphql", query, { email })
  );

  return (
    <div className="">
      <p className="">{session.user.nickname}</p>
      <button onClick={() => signOut()}>Sign out</button>
    </div>
  );
}

但是,这是一个错误。

这个特定问题的解决方法是为 session 定义一个 NextAuth 回调,但我认为这不是解决它的正确方法,因为我肯定需要做其他将来根据 session 对象中的值挂钩调用。

我该如何解决这个问题?

因为钩子在 React 内部由数组索引跟踪,所以你不能有条件地调用它们。每次呈现给定组件时,您都需要 same hook calls in the same order

您可以将 useSWR 和后续标记移至单独的组件以避免条件挂钩调用。

在下面的示例中,我也将登录调用移到了一个单独的组件中,但这并不是绝对必要的。如果你想离开内联,你可以 return null 代替。

export default function Profile() {
  const [session, loading] = useSession();

  if (loading) {
    return <p className="">loading...</p>;
  }

  return !session ? <SignIn /> : <UserStuff />
}

function SignIn () {
  signIn();
  return null;
}

function UserStuff () {
  const { data: user } = useSWR([USER_QUERY, session.email], (query, email) =>
    request("/api/graphql", query, { email })
  );

  return (
    <div className="">
      <p className="">{session.user.nickname}</p>
      <button onClick={() => signOut()}>Sign out</button>
    </div>
  );

}