Home > other >  How to /WAIT A SECOND/ to navigate after user signed in in a restricted route?
How to /WAIT A SECOND/ to navigate after user signed in in a restricted route?

Time:01-05

So what I mean is, I have a functionality of after user signed in, navigate him/her to the homepage in a second, such as:

const handleSignIn = async (e) => {
    e.preventDefault();

    const user = await signIn(formData);

    if (user) {
      toast.success('Signed In!');

      setTimeout(() => {
        navigate('/');
      }, 1000);
    } else {
      toast.error('Bad user credentials!');
    }
  };

But, I built a protected route, such as:

function App() {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setIsLoading(true);

      if (user) {
        setUser(user);
      } else {
        setUser(null);
      }

      setIsLoading(false);
    });

    return unsubscribe;
  }, []);

  if (isLoading) return <Spinner />;

  return (
    <>
      <Router>
        <Routes>
          <Route path='/' element={<PrivateRoute />}>
            <Route index element={<Explore />} />
            <Route path='/offers' element={<Offers />} />
            <Route path='/profile' element={<Profile />} />
            <Route path='/contact/:landlordId' element={<Contact />} />
            <Route path='/create-listing' element={<CreateListing />} />
            <Route path='/category/:categoryName' element={<Category />} />
            <Route path='/category/:categoryName/:id' element={<Listing />} />
          </Route>
          <Route
            path='/sign-in'
            element={!user ? <SignIn /> : <Navigate to='/' />}
          />
          <Route
            path='/sign-up'
            element={!user ? <SignUp /> : <Navigate to='/' />}
          />
          <Route
            path='/forgot-password'
            element={!user ? <ForgotPassword /> : <Navigate to='/' />}
          />
        </Routes>
        {user && <Navbar />}
      </Router>

      <ToastContainer autoClose={1000} />
    </>
  );
}

export default App;

So the problem here is, whenever user signs in or signs out,the onAuthStateChanged gets executed, therefore it enforce app to re-render in order to understand who's logged in and logged out then behave accordingly, like restrict some routes and allow others.

When user signs in, I'd like to show some toast message BUT it triggers the App level state and before I show toast and navigate user, it automatically navigates user into the homepage due to the restriction, how can I wait a second before doing that?

CodePudding user response:

Can't you just wait for x amount of time before calling setUser()? That is because setUser() updates the user value, which triggers navigation.

useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
        setIsLoading(true);

        setTimeout(() => {
            if (user) {
                setUser(user);
            } else {
                setUser(null);
            }

            setIsLoading(false);
        }, 1000);
    });

    return unsubscribe;
}, []);

Alternatively, use async/await with a custom wait async function that will avoid nesting:

const wait = async (d) => new Promise(r => setTimeout(d, r));

useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, async (user) => {
        setIsLoading(true);

        await wait(1000);

        if (user) {
            setUser(user);
        } else {
            setUser(null);
        }

        setIsLoading(false);
    });

    return unsubscribe;
}, []);

CodePudding user response:

Allow the SignIn, component to handle the redirect itself. You have two different pieces of logic that are redirecting to "/"

Instead of this:

          <Route
            path='/sign-in'
            element={!user ? <SignIn /> : <Navigate to='/' />}
          />

Switch to this:

          <Route
            path='/sign-in'
            element={<SignIn />}
          />

If that causes a problem (ie, if you want to bypass SignIn and go right to / if the user is already logged in), you should add a useEffect call to SignIn and call navigate('/'); there if necessary.

  •  Tags:  
  • Related