Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

266
Views
React.js, Auth Component does not redirect properly

I have created this Auth Component and it works fine. Except that, It does not redirect if the unauthenticated user tries to visit /dashboard.

The backend upon receiving /api/me request, knows the user by having the cookie. So I have (Cookie-Session) Authentication technique.

export const UserContext = createContext();

const Auth = ({ children }) => {
  const [user, setUser] = useState(null);
  const [gotUser, setGotUser] = useState(false);

  const navigate = useNavigate();

  const getUser = async () => {
    const res = await fetch('/api/me');
    const data = await res.json();
    setUser(data);
    if (user) {
      setGotUser(true);
    }
  };

  useEffect(() => {
    if (!gotUser) {
      getUser();
    }
  }, [user, gotUser, navigate]);

  if (!user) {
    navigate('/login');
  }
  console.log(user);

  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
};

So the main issue is that no redirection done. Also, The user passed to the context is not updated properly. Maybe because I am confused about what to use in useEffect .

Any help is appreciated.

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Issues

There are a couple issues:

  1. The "unauthenticated" state matches the "I don't know yet" state (i.e. the initial state value) and the component is redirecting too early. It should wait until the user state is confirmed.
  2. The navigate function is called as an unintentional side-effect directly in the body of the component. Either move the navigate call into a useEffect hook or render the Navigate component to issue the imperative navigation action.

Solution

Use an undefined initial user state and explicitly check that prior to issuing navigation action or rendering the UserContext.Provider component.

const Auth = ({ children }) => {
  const [user, setUser] = useState(); // <-- initially undefined

  const navigate = useNavigate();

  const getUser = async () => {
    try {
      const res = await fetch('/api/me');
      const data = await res.json();
      setUser(data); // <-- ensure defined, i.e. user object or null value
    } catch (error) {
      // handler error, set error state, etc...
      setUser(null); // <-- set to null for no user
    }
  };

  useEffect(() => {
    if (user === undefined) {
      getUser();
    }
  }, [user]);

  if (user === undefined) {
    return null; // <-- or loading indicator, spinner, etc
  }

  // No either redirect to log user in or render context provider and app
  return user
    ? <Navigate to="/login" replace />
    : <UserContext.Provider value={user}>{children}</UserContext.Provider>;
};
about 4 years ago · Juan Pablo Isaza Report

0

useEffect runs after your JSX is rendered, so as your code is made, on a page refresh this if (!user) that calls navigate('/login') will always pass, as before the useEffect does its work, user is null, that inital value you gave to useState. Yet it's not redirecting because navigate does not work inside JSX, it should be replaced with Navigate the component.

Also, in getUser, you have this if (user) juste after setUser(data), that wouldn't work well as user won't get updated immediately, as updating a state is an asynchronous task which takes effect after a re-redner .

To fix your problems you can add a checking state, return some loader while the user is being verified. Also you can optimise a little bit your code overall, like getting ride of that gotUser state:

export const UserContext = createContext();

const Auth = ({ children }) => {
  const [user, setUser] = useState(null);
  const [checking, setChecking] = useState(true);

  const getUser = async () => {
    try {
      const res = await fetch("/api/me");
      const data = await res.json();
      setUser(data);
    } catch (error) {
      setUser(null);
    } finally {
      setChecking(false);
    }
  };

  useEffect(() => {
    if (!user) {
      getUser();
    }
  }, [user]);

  if (checking) {
    return <p>Checking...</p>;
  }

  if (!user) {
    return <Navigate to="/login" replace />
  }

  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
};

export default Auth;
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!