skip to Main Content

I’m currently using the useXXXLazyQuery hook of rtk query for handling the login of my page, the problem is that i don’t have the latest data in my ProtectedRoute component.

The code is as following:

ProtectedRoute Component

import { type FC, type ReactNode } from 'react'
import { Navigate } from 'react-router-dom'
import { useLazyAuthQuery } from 'services/auth'

interface ProtectedRouteProps {
  children: ReactNode
}

const ProtectedRoute: FC<ProtectedRouteProps> = ({ children }) => {
  const [, results] = useLazyAuthQuery()

  if (results.data?.message !== 'authenticated') {
    return <Navigate to="/" replace />
  }

  return children
}

export { ProtectedRoute }

And that’s when i call the lazyQuery hook:


  ...
  const navigate = useNavigate()
  const [trigger, results] = useLazyAuthQuery()

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault()
    const data = new FormData(event.currentTarget)

    trigger({
      username: data.get('username'),
      password: data.get('password'),
    })
      .unwrap()
      .then(() => {
        navigate('/table')
      })
  }
  ...

The results of the useLazyAuthQuery on the ProtectedRoute component is always uninitialized so whenever I try to login the ProtectedRoute component acts as it should leaving me out of the Application. How can I access the latest data on the ProtectedRoute component?

2

Answers


  1. You misunderstand useLazyQuery.
    useLazyQuery is a hook that will always start "unattached" and then allows you to execute the trigger function to attach this one hook instance to a query (or start a new one).
    But each useLazyQuery is on it’s own – calling the trigger function of one will not trigger all others, as in the end they could all have different arguments to their endpoint.

    Login or Signup to reply.
  2. To fix this, you can use a trick with React’s useEffect hook. This hook lets you run some code whenever certain things change. In your case, you want to check if the user is logged in every time the login status changes.

    Here’s how you can do it:

    1. Use useEffect to Listen for Login Status Changes: You add a piece of code that runs whenever the login status changes. This code checks if the user is logged in. If they are, it does nothing and shows the protected page. If not, it redirects them to the login page.

    2. Wait Until Login Status is Known: Before showing the protected page, you wait until you know if the user is logged in. This way, you never show the protected page to someone who isn’t logged in.

    By doing this, you make sure that the protected page only shows up to users who are actually logged in, solving the problem of the page not knowing the latest login status.

    import { useEffect } from 'react';
    import { Navigate } from 'react-router-dom';
    import { useLazyAuthQuery } from 'services/auth';
    
    interface ProtectedRouteProps {
      children: ReactNode;
    }
    
    const ProtectedRoute: FC<ProtectedRouteProps> = ({ children }) => {
      const [, results] = useLazyAuthQuery();
    
      // Use useEffect to check authentication status
      useEffect(() => {
        if (results.data?.message === 'authenticated') {
          // If authenticated, do nothing
        } else {
          // If not authenticated, redirect to login
          return <Navigate to="/" replace />;
        }
      }, [results.data?.message]); 
    
      // Initially return null to wait for authentication
      return null;
    };
    
    export { ProtectedRoute };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search