I want to redirect my page URL conditionally. I was using but it did not redirect my page automatically . After refresh the page it works. But I want after changes it redirect automatically.
My Previous Code was:
<Route path='/login' element={ !token ? <Login/> : <Navigate replace to="/dashboard" /> } />
CodePudding user response:
You can't do that. You have to make a context and routing file for that
here is the example of auth routing
import axios from "axios";
import { useState, createContext, useContext, useEffect } from "react";
const AuthContext = createContext();
const AuthProvider = ({ children }) => {
const [auth, setAuth] = useState({
user: null,
token: "",
});
// NOTE axios config
axios.defaults.baseURL = process.env.REACT_APP_API;
axios.defaults.headers.common["Authorization"] = auth?.token;
useEffect(() => {
const data = localStorage.getItem("auth");
if (data) {
const parsed = JSON.parse(data);
setAuth({
user: parsed.user,
token: parsed.token,
});
}
}, []);
return (
<AuthContext.Provider value={[auth, setAuth]}>
{children}
</AuthContext.Provider>
);
};
const useAuth = () => useContext(AuthContext);
export { AuthProvider, useAuth };
and put the context in index.js
src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { AuthProvider } from "./context/auth";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<AuthProvider>
<App />
</AuthProvider>
);
reportWebVitals();
now, you have to make the routing src/components/route/privateRoute.js
import axios from "axios";
import { Outlet } from "react-router-dom";
import { useEffect, useState } from "react";
import { useAuth } from "../../context/auth";
import Loading from "./Loading";
export default function PrivateRoute() {
// NOTE context
const [auth] = useAuth();
// NOTE ok
const [ok, setOk] = useState(false);
useEffect(() => {
const authCheck = async () => {
const { data } = await axios.get("auth-check");
if (data.ok) {
setOk(true);
} else {
setOk(false);
}
};
if (auth?.token) authCheck();
}, [auth?.token]);
return ok ? <Outlet /> : <Loading />;
}
Oh I use Loading for the navigation, here it is src/components/routes/loading.js
import { useEffect, useState } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import loadingGIF from "../../images/loading.gif";
export default function Loading({ path = "/login" }) {
// NOTE state
const [count, setCount] = useState(3);
// NOTE variable
const location = useLocation();
const navigate = useNavigate();
useEffect(() => {
const interval = setInterval(() => {
setCount((currentCount) => --currentCount);
}, 1000);
count === 0 &&
navigate(path, {
state: location.pathname,
});
return () => clearInterval(interval);
}, [count, location, navigate, path]);
return (
<div className="d-flex justify-content-center align-items-center vh-90">
<img src={loadingGIF} alt="loading" width="400" height="500" />
</div>
);
}
The last but not least, put the routes you want to give the rule with inside it
App.js
<Route path="/dashboard" element={<PrivateRoute />}>
<Route path="user" element={<UserDashboard />} />
<Route path="user/orders" element={<UserOrders />} />
<Route path="user/profile" element={<UserProfile />} />
</Route>
Good luck
CodePudding user response:
You can handle the redirect inside components, or wrap them with a component that does it
Inside login
let navigate = useNavigate();
useEffect(() => {
if (isAuthenticated) {
let to = `/dashboard`; // some default auth route
navigate(from, { replace: true });
}
}, [isAuthenticated])
Inside authencitated components
import { Navigate, useNavigate } from 'react-router-dom';
let location = useLocation();
if (!isAuthenticated) {
console.log('unauthenticated redirect back to login')
return (<Navigate to="/login" state={{ from: location }} replace />);
}
Keep the routes standard
<Route path='/login' element={<Login/>} />
If you want a better way, then I suggest reading a blog by kent C. Dodds on Authentication in React
Hope it helps