你如何在 React 中调用 useContext 而不破坏钩子规则?

Posted

技术标签:

【中文标题】你如何在 React 中调用 useContext 而不破坏钩子规则?【英文标题】:How do you call useContext in React without breaking rules of hooks? 【发布时间】:2022-01-21 11:59:58 【问题描述】:

我正在尝试了解如何在我的上下文提供程序中为 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;

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

【问题讨论】:

const githubLogin, googleLogin = useUser() 在顶部,然后到按钮:onClick=githubLogin ? 这不是真的关于 next.js,而是反应。 【参考方案1】:

将对useUser 的调用移动到组件的主体中,然后在需要时调用它返回的函数。我认为没有理由使用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>
  );

【讨论】:

以上是关于你如何在 React 中调用 useContext 而不破坏钩子规则?的主要内容,如果未能解决你的问题,请参考以下文章

React:useContext,如何从外部组件中检索它?

如何在类组件中使用 React.useContext(AuthContext) 来触发 index.js 文件中的条件集

如何测试组件中的react useContext useReducer调度

在 React 中使用 useContext 和 useReducer 创建新的键值对

react中 useContext 和useReducer的使用

使用 React 钩子 useContext 避免不必要的重新渲染