如何在不违反钩子规则的情况下在 React 中调用 useContext?

How do you call useContext in React without breaking rules of hooks?

我正在尝试了解如何在上下文提供程序中为 Google 或 Github 调用登录函数。

在不破坏钩子规则的情况下,在 Next JS 中调用上下文提供程序的正确方法是什么?

// user.js
const Context = createContext();

const Provider = ({ children }) => {
  const [user, setUser] = useState(supabase.auth.user());
  const [isLoading, setIsLoading] = useState(true);
  const router = useRouter();

  useEffect(() => {
    const getUserProfile = async () => {
      const sessionUser = supabase.auth.user();

      if (sessionUser) {

        //removed for brevity

        setUser({
          ...sessionUser,
          ...profile,
        });

        setIsLoading(false);
      }
    };

    getUserProfile();

    supabase.auth.onAuthStateChange(() => {
      getUserProfile();
    });
  }, []);

  const githubLogin = async () => {
    await supabase.auth.signIn({
      provider: "github",
    });
  };

  const googleLogin = async () => {
    await supabase.auth.signIn({
      provider: "google",
    });
  };

  const logout = async () => {
    await supabase.auth.signOut();
    setUser(null);
    router.push("/");
  };

  const exposed = {
    user,
    googleLogin,
    githubLogin,
    logout,
    isLoading,
  };

  return <Context.Provider value={exposed}>{children}</Context.Provider>;
};

export const useUser = () => useContext(Context);
export default Provider;

和我的登录页面

// login.js
const Login = () => {
    
    const handleGithubLogin = () => {
      const { githubLogin } = useUser();
      useEffect(githubLogin, []);
    }

    const handleGoogleLogin = () => {
      const { googleLogin } = useUser();
      useEffect(googleLogin, []);
    };

  return (
    <div>
      <button onClick={handleGithubLogin}>Login with Github</button>
      <button onClick={handleGoogleLogin}>Login with Google</button>
    </div>
  );
  }

export default Login;

如何在不破坏钩子规则的情况下调用这些登录函数?从我的登录页面调用上下文提供程序的最佳方式是什么?

将对 useUser 的调用移动到组件的主体中,然后在需要时调用它 returns 的函数。我认为没有理由使用 useEffect.

const Login = () => {
  const { githubLogin, googleLogin } = useUser();

  const handleGithubLogin = () => {
    githubLogin();
  }

  const handleGoogleLogin = () => {
    googleLogin();
  }

  return (
    <div>
      <button onClick={handleGithubLogin}>Login with Github</button>
      <button onClick={handleGoogleLogin}>Login with Google</button>
    </div>
  );
}

// OR:
const Login = () => {
  const { githubLogin, googleLogin } = useUser();

  return (
    <div>
      <button onClick={githubLogin}>Login with Github</button>
      <button onClick={googleLogin}>Login with Google</button>
    </div>
  );
}