import { useState, useEffect } from "react";
import { useJwt } from "react-jwt";
import { useDispatch, useSelector } from "react-redux";
import {useNavigate} from "react-router-dom"
import { setUserData, clearUserData } from "./features/auth/authSlice";
import { getAccount } from "./features/user/dataSlice";
import Header from "./components/Header";
import Announcement from "./components/Announcement";
import Sidebar from "./components/Sidebar";
import Navbar from "./components/Navbar";
import Loader from "./components/Loader";
import Home from "./pages/HomePage";
import FundAccount from "./pages/FundAccount";
import Withdraw from "./pages/Withdraw";
import BuyData from "./pages/BuyData";
import BuyAirtime from "./pages/BuyAirtime";
import PayCableTv from "./pages/PayCableTv";
import PayElectricity from "./pages/PayElectricity";
import Profile from "./pages/Profile";
import Setting from "./pages/Setting";
import Transactions from "./pages/Transactions";
const BASE_URL =
import.meta.env.VITE_MODE === "DEV"
? import.meta.env.VITE_BASE_URL_TEST
: import.meta.env.VITE_BASE_URL_LIVE;
function Dashboard({currentPage, setCurrentPage}) {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [showMenu, setShowMenu] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [active, setActive] = useState(false);
const [isTransActive, setIsTransActive] = useState(false);
const [urlState, setUrlState] = useState("#dashboard")
const navigate = useNavigate()
const toggleMenu = () => setIsMenuOpen((prevState) => !prevState);
const closeAllMenu = () => {
showMenu === true ? setShowMenu(false) : null;
if (active) {
setActive(false);
}
if (isTransActive) {
setIsTransActive(false);
}
};
const handleLogout = () => {
localStorage.removeItem("user");
localStorage.removeItem("account");
dispatch(clearUserData());
window.location = `${BASE_URL}/users/logout`;
};
const showPage = (pageTitle) => {
const url = window.location.pathname;
let newState = url;
const fragments = [
"#dashboard",
"#fund-account",
"#withdraw",
"#transactions",
"#buy-data",
"#buy-airtime",
"#pay-electricity-bill",
"#pay-cable-tv",
"#profile",
"#setting",
];
// const currentFragment = window.location.href.split("#")[1]
// console.log(currentFragment)
// console.log(pageTitle);
// console.log(url);
switch (pageTitle) {
case "Home":
newState += "#dashboard";
//window.history.replaceState(null, "", newState);
return (
<Home
setCurrentPage={setCurrentPage}
setIsLoading={setIsLoading}
isTransActive={isTransActive}
setIsTransActive={setIsTransActive}
/>
);
case "Fund Account":
newState += "#fund-account";
// window.history.replaceState(null, "", newState);
return <FundAccount setIsLoading={setIsLoading} />;
case "Withdraw":
newState += "#withdraw";
// window.history.replaceState(null, "", newState);
return <Withdraw setIsLoading={setIsLoading} />;
case "Transactions":
newState += "#transactions";
// window.history.replaceState(null, "", newState);
return <Transactions setIsLoading={setIsLoading} />;
case "Buy Data":
newState += "#buy-data";
// window.history.replaceState(null, "", newState);
return <BuyData setIsLoading={setIsLoading} />;
case "Buy Airtime":
newState += "#buy-airtime";
// window.history.replaceState(null, "", newState);
return <BuyAirtime setIsLoading={setIsLoading} />;
case "Pay Electricity Bill":
newState += "#pay-electricity";
// window.history.replaceState(null, "", newState);
return <PayElectricity setIsLoading={setIsLoading} />;
case "Pay Cable Tv":
newState += "#pay-cable-tv";
// window.history.replaceState(null, "", newState);
return <PayCableTv setIsLoading={setIsLoading} />;
case "Profile":
newState += "#profile";
// window.history.replaceState(null, "", newState);
return <Profile setIsLoading={setIsLoading} />;
case "Setting":
newState += "#setting";
// window.history.replaceState(null, "", newState);
return <Setting setIsLoading={setIsLoading} />;
default:
newState += "#dashboard";
// window.history.replaceState(null, "", newState);
return <Home setIsLoading={setIsLoading} />;
}
};
const dispatch = useDispatch();
const { user } = useSelector((state) => state.auth);
const { isDataLoading } = useSelector((state) => state.data);
const { isPurchaseLoading } = useSelector((state) => state.purchase);
const account = JSON.parse(localStorage.getItem("account"));
const urlParams = new URLSearchParams(window.location.search);
const token = urlParams.get("token");
const getToken = token && useJwt(token);
useEffect(() => {
if (token && getToken && !getToken?.isExpired && !user) {
localStorage.setItem("user", JSON.stringify(getToken.decodedToken));
dispatch(setUserData(getToken.decodedToken));
}
}, [getToken?.decodedToken, dispatch]);
useEffect(() => {
if (user) dispatch(getAccount(user.id));
}, [user, dispatch]);
useEffect(() => {
const uri = new URL(`${window.location.protocol}//${window.location.host}`)
}, [])
return (
<>
{isDataLoading && <Loader />}
{isLoading && <Loader />}
{isPurchaseLoading && <Loader />}
<div
className={`layout-wrapper layout-content-navbar ${
isMenuOpen ? "layout-menu-expanded" : ""
}`}
onClick={(e) => closeAllMenu(e)}
>
<div className="layout-container">
<Sidebar
currentPage={currentPage}
setCurrentPage={setCurrentPage}
setIsMenuOpen={setIsMenuOpen}
handleLogout={handleLogout}
/>
{/* <!-- Layout container --> */}
<div className="layout-page">
<Navbar
isMenuOpen={isMenuOpen}
setIsMenuOpen={setIsMenuOpen}
handleClick={toggleMenu}
setCurrentPage={setCurrentPage}
showMenu={showMenu}
setShowMenu={setShowMenu}
handleLogout={handleLogout}
/>
{/* <!-- Content wrapper --> */}
<div className="content-wrapper">
{/* <!-- Content --> */}
<div className="container-xxl flex-grow-1 container-p-y">
{currentPage === "Profile" ||
currentPage === "Setting" ||
currentPage === "Transactions" ? (
""
) : (
<div className="row">
<Header
account={account}
setCurrentPage={setCurrentPage}
active={active}
setActive={setActive}
/>
<Announcement />
</div>
)}
{showPage(currentPage)}
</div>
<footer className="content-footer footer bg-footer-theme">
<div className="container-xxl d-flex flex-wrap justify-content-between py-2 flex-md-row flex-column">
</div>
</footer>
<div className="content-backdrop fade"></div>
</div>
{/* <!-- Content wrapper --> */}
</div>
{/* <!-- / Layout page --> */}
</div>
{/* <!-- Overlay --> */}
<div
className="layout-overlay layout-menu-toggle"
onClick={() => setIsMenuOpen(false)}
></div>
</div>
</>
);
}
export default Dashboard;
I am trying to create a react application which vite where I send data from a backend with a different url (http://localhost:3500). I make a redirect from the backend to the vite frontend and send the data through a query param called token then I use the useJWT to decode the token and make I dispatch, my problem is that I want to change the page url from localhost:5173?token=… to localhost:5173#dashboard but when I use the window.location.pushState(null, "", newState) or replaceState(null, "", newState), I get the error below
Warning: React has detected a change in the order of Hooks called by Dashboard. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
Previous render Next render
-
useContext useContext
-
useContext useContext
-
useRef useRef
-
useCallback useCallback
-
useRef useRef
-
useMemo useMemo
-
useSyncExternalStore useSyncExternalStore
-
useEffect useEffect
-
useDebugValue useDebugValue
-
useDebugValue useDebugValue
-
useContext useContext
-
useRef useRef
-
useCallback useCallback
-
useRef useRef
-
useMemo useMemo
-
useSyncExternalStore useSyncExternalStore
-
useEffect useEffect
-
useDebugValue useDebugValue
-
useDebugValue useDebugValue
-
useContext useContext
-
useRef useRef
-
useCallback useCallback
-
useRef useRef
-
useMemo useMemo
-
useSyncExternalStore useSyncExternalStore
-
useEffect useEffect
-
useDebugValue useDebugValue
-
useDebugValue useDebugValue
-
useState useEffect
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^at Dashboard (http://localhost:5173/src/Dashboard.jsx?t=1692559813161:41:20)
at App
at Provider (http://localhost:5173/node_modules/.vite/deps/react-redux.js?v=cb62aef7:1507:3)
if there is anyone who understands hooks or have a better way I can send data from a different url to this vite url without having to cause this problem should please help me out with the solution. Thanks
I tried moving the useEffect way above all my code, but it still tells me about the problem and I also found out that the error occurs whenever there is a useEffect and window.history.pushState in One Component
And I a thinking of changing the whole code to use react-router-dom
2
Answers
Your problem lies in
component.
Basically, you have some conditional hooks (etc: hooks inside if statements) and this is bad, at least for react.
the problem is with this line:
there is a conditional usage of a hook (the hook is executed only when
token
is thruthy)Instead, try passing
token
intouseJwt
in all cases, e.g.:or, if you need to handle undefined tokens, you could do something like this.