Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Protected routes not accessible even after signing or logging in

I am making a site whereby after the user signs in, the user is meant to be redirected to the home page. The homepage and all the other pages of the site are only accessible by signed in users but even after a user signs in(firebase auth), the rest of the site(protected routes) is still not accessible and the only page accessible is the login page. The technologies I am using are react, react router dom and firebase and this is how my code looks like, starting with the App.js

import Home from "./pages/home/Home";
import Login from "./pages/login/Login";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import List from "./pages/list/List";
import User from "./pages/user/User";
import AddNew from "./pages/addnew/AddNew";
import { useContext } from "react";
import { AuthContext } from "./context/AuthContext";

function App() {
  const {currentUser} = useContext(AuthContext);
  
  const RequireAuth = ({ children }) => {
    return currentUser ? children : <Navigate to="/login" />;
  };


  return (
    <div className="App">
      <BrowserRouter>
        <Routes>
          <Route path="/login" exact element={<Login />} />
          <Route path="/" exact element={ <RequireAuth> <Home /> </RequireAuth> } />
          <Route path="/users" exact element={<RequireAuth><List /></RequireAuth>} />
          <Route path="/users/:id" exact element={<RequireAuth><User /></RequireAuth>} />
          <Route path="/add" exact element={<RequireAuth><AddNew /></RequireAuth>} />
        </Routes>
      </BrowserRouter>
    </div>
  );
}

export default App;

And then followed by the login.js page

import React,{useState} from 'react'
import { useContext } from 'react';
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from '../../firebase';
import "./login.css";
import {useNavigate} from "react-router-dom";
import { AuthContext } from '../../context/AuthContext';

export default function Login() {
  const [error, seterror] = useState(false);
  const [email, setemail] = useState("");
  const [password, setpassword] = useState("");
  const navigate = useNavigate();
  const {dispatch} = useContext(AuthContext)
  
  const handleLogin = (e) => {
    e.preventDefault();

    signInWithEmailAndPassword(auth, email, password)
      .then((userCredential) => {
        const user = userCredential.user;
        dispatch({type: "LOGIN", payload: user});
        navigate("/");
      })
      .catch((error) => {
        seterror(true);
        console.log(error.message);
      });
  }


  return (
    <div className='login'>
        <form onSubmit={handleLogin}>
          <input className='ok' type="email" placeholder='email' onChange={e => setemail(e.target.value)} />
          <input className='ok' type="password" placeholder='password' onChange={e => setpassword(e.target.value)} />
          <button className='sb'>Submit</button>
          {error && <span className='ks'>Wrong email or password</span>}
        </form>
    </div>
  )
}

And then I have the authreducer.js file that deals with the state

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const AuthReducer = (state, action) => {
    switch (action.type) {
        case "LOGIN": {
            return {
                currentUser: action.payload,
            }
        }
        case "LOGOUT": {
            return {
                currentUser: null
            }
        }
        default:
            return state;
    }
}

export default AuthReducer

And finally the authcontext.js file

import { createContext, useEffect, useReducer } from "react";
import AuthReducer from "./AuthReducer";

const INITIAL_STATE = {
    currentUser: JSON.parse(localStorage.getItem("user")) || null,
}

export const AuthContext = createContext(INITIAL_STATE);

export const AuthContextProvider = ({children}) => {
    const [state, dispatch] = useReducer(AuthReducer, INITIAL_STATE);

    useEffect(() => {
        localStorage.setItem("user", JSON.stringify(state.currentUser))
    }, [state.currentUser])

    return (
        <AuthContext.Provider value={{current: state.current, dispatch}}>
            {children}
        </AuthContext.Provider>
    )
}

I do not know what could be causing this problem but I have an idea that it has something to do with the state because it was redirecting well before I started combining it with the state. What could be the problem

>Solution :

Issue

From that I can see, the App isn’t destructuring the correct context value to handle the conditional route protection.

The AuthContextProvider provides a context value with current and dispatch properties

<AuthContext.Provider value={{ current: state.current, dispatch }}>
  {children}
</AuthContext.Provider>

but App is accessing a currentUser property, which is going to be undefined because state.current is undefined.

const { currentUser } = useContext(AuthContext);

const RequireAuth = ({ children }) => {
  return currentUser ? children : <Navigate to="/login" />;
};

The Navigate component will always be rendered.

Solution

Assuming the handleLogin handler correctly updates the state then the solution is to be consistent with state properties.

<AuthContext.Provider value={{ currentUser: state.currentUser, dispatch }}>
  {children}
</AuthContext.Provider>

const { currentUser } = useContext(AuthContext);

const RequireAuth = ({ children }) => {
  return currentUser ? children : <Navigate to="/login" />;
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading