首页 > 解决方案 > 如果用户为空,则反应 useEffect。重定向

问题描述

我正在尝试在下一个 JS 中创建一条受保护的路线。如果没有用户到登录页面,我添加了一个使用效果来重定向

  const analytics = () => {
  const { userLoaded, user, signOut, session, userDetails, subscription } =
    useUser();
  const router = useRouter();
  console.log(session);

  useEffect(() => {
    setInterval(() => {
      if (!session) router.replace("/admindashboard");
    }, 3000);
  }, [session]);

  return (
    <>
      <Dashboard />
      <p>Coming soon</p>
    </>
  );
};

导出默认分析;

问题是我正在为我调用用户的 supabase 使用自定义钩子。当页面由于某种原因加载时它是 null 然后对用户来说是 true 但是因为它是 null 它在不需要时重定向我对如何防止这种情况感到困惑

语境

import { useEffect, useState, createContext, useContext } from "react";
import { supabase } from "../utils/supabaseClient";

export const UserContext = createContext();

export const UserContextProvider = (props) => {
  const [userLoaded, setUserLoaded] = useState(false);
  const [session, setSession] = useState(null);
  const [user, setUser] = useState(null);
  const [userDetails, setUserDetails] = useState(null);
  const [subscription, setSubscription] = useState(null);

  useEffect(() => {
    const session = supabase.auth.session();
    setSession(session);
    setUser(session?.user ?? null);
    const { data: authListener } = supabase.auth.onAuthStateChange(
      async (event, session) => {
        setSession(session);
        setUser(session?.user ?? null);
      }
    );

    return () => {
      authListener.unsubscribe();
    };
  }, []);
  const updateAvatar = (url) =>
    supabase.auth.update({
      data: { avatar_url: url },
    });

  const updateCardFav = async (favId) =>
    await supabase.from("user_faved").insert([{ name: favId }]);

  const updateUserName = (userEnteredName) => {
    supabase.auth.update({
      data: { full_name: userEnteredName },
    });
  };
  const getUserDetails = () => supabase.from("users").select("*").single();
  const getSubscription = () =>
    supabase
      .from("subscriptions")
      .select("*, prices(*, products(*))")
      .in("status", ["trialing", "active"])
      .single();

  useEffect(() => {
    if (user) {
      Promise.allSettled([getUserDetails(), getSubscription()]).then(
        (results) => {
          setUserDetails(results[0].value.data);
          setSubscription(results[1].value.data);
          setUserLoaded(true);
        }
      );
    }
  }, [user]);

  const value = {
    session,
    user,
    updateCardFav,
    userDetails,
    updateUserName,
    userLoaded,
    subscription,
    updateAvatar,
    signIn: (options) => supabase.auth.signIn(options),
    signUp: (options) => supabase.auth.signUp(options),
    signOut: () => {
      setUserDetails(null);
      setSubscription(null);
      return supabase.auth.signOut();
    },
  };
  return <UserContext.Provider value={value} {...props} />;
};

export const useUser = () => {
  const context = useContext(UserContext);
  if (context === undefined) {
    throw new Error(`useUser must be used within a UserContextProvider.`);
  }
  return context;
};

标签: javascriptreactjsnext.js

解决方案


您只需将 isLoading 添加到用户即可,这很简单。

isLoading 的第一个值必须为真。

useEffect(() => {
  if (!isLoading && !user) {
    router.push("/admindashboard");
    return;
  }
  return;
}, [user, isLoading]);

在你的钩子里

const [isLoading, setLoading] = useState(true)
useEffect(() => {
  if (user) {
    Promise.allSettled([getUserDetails(), getSubscription()]).then(
      (results) => {
        setUserDetails(results[0].value.data);
        setSubscription(results[1].value.data);
        setUserLoaded(true);
        setLoading(false);
      }
    ).catch(err => {
      console.log(err);
      setLoading(false);
      setUserLoaded(false);
    });
  }
}, [user]);


推荐阅读