My goal was to create protected routes. This now kinda works but I manually need to refresh the page for it to navigate me to the dashboard after logging in. At the moment all that happens is: I log in, get the success toast and it tries to navigate to the dashboard but it lands back on the landing page. Then I need to reload the page manually to access the dashboard.
routes.jsx
import React, { useContext } from 'react';
import { UserContext } from './context/userContext';
import {
BrowserRouter as Router,
Route,
Routes,
Navigate,
} from 'react-router-dom';
import Dashboard from './pages/dashboard';
import Landingpage from './pages/landingpage';
import Profile from './pages/profile';
import Login from './pages/auth/login';
import Register from './pages/auth/register';
import Friends from './pages/friends';
import Notifications from './pages/notifications';
import { Loader } from 'lucide-react';
function MyRoutes() {
const { user, loading } = useContext(UserContext);
if (loading) {
return <Loader />;
}
return (
<Router>
<Routes>
{user ? (
<>
<Route path='/dashboard' element={<Dashboard />} />
<Route path='/profile' element={<Profile />} />
<Route path='/friends' element={<Friends />} />
<Route
path='/notifications'
element={<Notifications />}
/>
<Route
path='*'
element={<Navigate to='/dashboard' />}
/>
</>
) : (
<>
<Route path='/' element={<Landingpage />} />
<Route path='/login' element={<Login />} />
<Route path='/register' element={<Register />} />
<Route path='*' element={<Navigate to='/login' />} />
</>
)}
</Routes>
</Router>
);
}
export default MyRoutes;
userContext.jsx
import React, { createContext, useState, useEffect } from 'react';
import axios from 'axios';
export const UserContext = createContext();
export const UserContextProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
axios
.get('/profile')
.then((response) => {
if (response.data.success) {
setUser(response.data.user);
} else {
setUser(null);
}
})
.catch(() => {
setUser(null);
})
.finally(() => {
setLoading(false);
});
}, []);
return (
<UserContext.Provider value={{ user, setUser, loading, setLoading }}>
{children}
</UserContext.Provider>
);
};
authContoller.jsx (backend route /profile)
const getProfile = async (req, res) => {
logger.info(texts.INFO.ATTEMPTING_PROFILE_RETRIEVAL);
const { token } = req.cookies;
if (token) {
jwt.verify(
token,
'idsfu&ASUDIhiedUioGYUYFHIUGTygbhbhY3427HS',
{},
async (err, decoded) => {
if (err) {
logger.warn(texts.WARNINGS.INVALID_TOKEN);
return res.json({ error: texts.WARNINGS.INVALID_TOKEN });
}
try {
const user = await User.findById(decoded.id).select(
'-password -goals'
);
if (!user) {
logger.warn(texts.WARNINGS.USER_NOT_FOUND);
return res
.status(404)
.json({ error: texts.WARNINGS.USER_NOT_FOUND });
}
logger.info(texts.SUCCESS.USER_LOGGED_IN(user.username));
res.json({ success: true, user });
} catch (error) {
logger.error(
texts.ERRORS.ERROR('user profile retrieval', error)
);
res.status(500).json({
error: texts.ERRORS.USER_PROFILE_RETRIEVAL,
});
}
}
);
} else {
logger.warn(texts.WARNINGS.NO_TOKEN_FOUND);
res.json(texts.WARNINGS.NO_TOKEN_FOUND);
}
};
login.jsx (only the logic)
const [data, setData] = useState({
emailOrUsername: '',
password: '',
});
const { setUser } = useContext(UserContext);
const navigate = useNavigate();
const { addToast } = useToast();
const loginUser = async (event) => {
event.preventDefault();
const { emailOrUsername, password } = data;
try {
const { data } = await axios.post('/login', {
emailOrUsername,
password,
});
if (data.error) {
addToast(data.error, 'error');
} else {
setUser(data.user);
setData({});
navigate('/dashboard');
addToast('Login erfolgreich!', 'success');
}
} catch (error) {
addToast(
'Login fehlgeschlagen. Bitte versuchen Sie es erneut. ' + error,
'error'
);
}
};```