I have created a protected Route on this code
import { useSelector } from "react-redux";
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { RootState } from "src/store";
const ProtectedRoute = () => {
const location = useLocation();
// const isToken = localStorage.getItem("token") !== "";
const { isAuthenticated, loading } = useSelector(
(state: RootState) => state.login
);
if (loading) return null;
return isAuthenticated ? (
<Outlet />
) : (
<Navigate to="/login" replace state={{ from: location }} />
);
};
export default ProtectedRoute;
check login and get token from localstorage and change link to dashboard from login
builder.addCase(login.fulfilled, (state, action) => {
const isToken = localStorage.getItem("token") !== "";
const Token = localStorage.getItem("token");
history.push("/dashboard");
return {
...state,
loading: false,
isAuthenticated: isToken,
token: Token,
...action.payload,
};
});
**Check Route path and change link accordingly **
<BrowserRouter>
<Routes>
<Route element={<Login />} path="/login" />
<Route path="/" element={<ProtectedRoute />}>
<Route path="dashboard" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
I want to make a protected route and change login page to dashboard page when user enter correctly and everything is working perfectly but after login the url change but component did not change it will stay on login page how to change compoent to dashboard page.
What I suspect you have done is to create a separate history
object reference in your state slice, e.g. createBrowserHistory
, and are using that to try and navigate. This will obviously update the URL but because this happens outside the main app router component it isn't aware of the URL change and won't rerender with the correct route matched.
Reducer functions are to be considered pure and free of side-effects, don't try to issue a navigation action from the reducer. Since login
is an asynchronous action you can await
it in the UI and issue the navigation action there.
Example:
Thunk action
const login = createAsyncAction(
"login",
async ({ username, password }, thunkAPI) => {
try {
const result = fetch(.....);
return /* auth result */
} catch(error) {
return thunkAPI.rejectWithValue(error);
}
},
);
...
builder.addCase(login.fulfilled, (state, action) => {
const token = localStorage.getItem("token");
return {
...state,
loading: false,
isAuthenticated: !!token,
token,
...action.payload,
};
});
...
Login UI
import { useNavigate } from 'react-router-dom';
...
const navigate = useNavigate();
const dispatch = useDispatch();
const loginHandler = async () => {
try {
await dispatch(login({ username, password })).unwrap();
navigate("/dashboard"); // <-- navigate here after login resolves
} catch(error) {
// handle login errors, rejected Promises, etc
}
};
...