This is the Login
component where I created the authentication state with the token
as false, and after login convert as true
function Login() {
const [user, setUser] = useState({ name: '', email: '' });
const [error, setError] = useState('');
const [auth, setAuth] = useState({ token: false })
console.log(auth)
const Login = (details) => {
console.log(details);
if (
details.name === adminUser.name &&
details.email === adminUser.email &&
details.password === adminUser.password
) {
console.log('Logged in');
setAuth({
token: true,
})
This works perfectly fine, but now when I try to pass it to the PrivateRoute
component, the auth
is undefined
const PrivateRoutes = ({ auth }) => {
console.log(auth)
return (
auth ? <Outlet/> : <Navigate to="/login"/>
)
}
Also this is my App.jsx
function App() {
return (
<Routes>
<Route element={<PrivateRoutes />}>
<Route path="/*" element={<MainPage />} />
</Route>
<Route path="/login" element={<Login />} />
</Routes>
);
}
What do I need to change to get the data from the state and my guard functionality to work?
CodePudding user response:
The auth
state should be in a common ancestor so it can be passed down as props.
Example:
function App() {
const [auth, setAuth] = useState({ token: false });
return (
<Routes>
<Route element={<PrivateRoutes auth={auth} />}>
<Route path="/*" element={<MainPage />} />
</Route>
<Route path="/login" element={<Login setAuth={setAuth} />} />
</Routes>
);
}
const PrivateRoutes = ({ auth }) => {
return auth.token ? <Outlet/> : <Navigate to="/login" replace />;
}
function Login({ setAuth }) {
const navigate = useNavigate();
const [user, setUser] = useState({ name: '', email: '' });
const [error, setError] = useState('');
const login = (details) => {
if (
details.name === adminUser.name &&
details.email === adminUser.email &&
details.password === adminUser.password
) {
setAuth({ token: true });
navigate(/* new target path */, { replace: true });
...
}
...
CodePudding user response:
So, to summarise, you want the state in the Login component to be able to access in PrivateRoutes component. React recommends a pattern called lifting state up to achieve such similar use cases .
The idea is to have the auth state variable in common parent to both LoginPage component and PrivateRoute Component and pass it to both child components.
Something similar to the below image
So now changing auth (state) in any one of the components will effect the other component too. You should pass down setAuth() to the component where you want to modify the auth state.
In your example, Login component must be able to modify auth so that PrivateRoute component can use that state. You need to pass setAuth() to Login component and auth variable to PrivateRoute
Refer the docs here
The answer by Drew Reese makes it clear with the code example. Please refer it.