I'm using React Router v6 and am creating private routes for my application. i must to close all routes except login until user is authenticated
this is my private route
import React from 'react';
import { Navigate } from 'react-router-dom';
import loginAction from '@/api/AuthProvider';
export function PrivateRoute({ children }) {
const { user } = loginAction();
return user ? children : <Navigate to="/login" />;
}
this is my request
export default function loginAction() {
return new Promise((resolve) => {
resolve({
user: {
fullName: 'Elon Mask',
dob: '2022-07-27T12:46:26.356Z',
email: '[email protected]',
defaultCurrency: 'USD'
},
token: 'DTYHKL57HGGJ'
});
}).then((data) => {
localStorage.setItem('token', data.token);
return data;
});
}
This is my App
export const App = () => {
return (
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />} />
<Route
element={
<PrivateRoute>
<AppLayout />
</PrivateRoute>
}
>
<Route
path="/"
element={
<PrivateRoute>
<Landing />
</PrivateRoute>
}
/>
<Route
path="/about"
element={
<PrivateRoute>
<About />
</PrivateRoute>
}
/>
<Route
path="/categories"
element={
<PrivateRoute>
<Categories />
</PrivateRoute>
}
/>
<Route
path="*"
element={
<PrivateRoute>
<Fallback />
</PrivateRoute>
}
/>
<Route
path="/expenses"
element={
<PrivateRoute>
<Expenses />
</PrivateRoute>
}
/>
</Route>
</Routes>
</BrowserRouter>
</QueryClientProvider>
);
};
but when i submit, it does not redirect me to the home page what i am doing wrong? Is there something I'm missing?
You're trying to use loginAction
as a react hook when in reality it's an asynchronous function that returns a promise.
The way that I would suggest solving this is converting the loginAction
action into a react hook. Read more about hooks here: https://reactjs.org/docs/hooks-intro.html
Essentially the two main parts of a hook are that:
use
such as useLoginAction
So the first change is wrapping loginAction into a hook:
If you don't understand how the useEffect
hook works, look at this: https://reactjs.org/docs/hooks-effect.html
import { useState, useEffect } from "react";
function loginAction() {
return new Promise((resolve) => {
resolve({
user: {
fullName: 'Elon Mask',
dob: '2022-07-27T12:46:26.356Z',
email: '[email protected]',
defaultCurrency: 'USD'
},
token: 'DTYHKL57HGGJ'
});
}).then((data) => {
localStorage.setItem('token', data.token);
return data;
});
}
export default function useLoginAction(){
const [data, setData] = useState({ user: null });
useEffect(() => {
loginAction().then((response) => setData(response));
}, []);
return data;
}
After that you can use the hook in your private route function. There are less repetitive ways to conditionally render the routes but that's outside the scope of this question:
import React from 'react';
import { Navigate } from 'react-router-dom';
import useLoginAction from '@/api/AuthProvider';
export function PrivateRoute({ children }) {
const { user } = useLoginAction();
return user ? children : <Navigate to="/login" />;
}
And this should work the way you're expecting it to work from my understanding.