I have used react-router
in App.jsx
where the parent component is the Main
component with following Routes
<Route path="/" element={<Main />}>
<Route path="login" element={<Login />} />
<Route path="signup" element={<SignUp />} />
</Route>
In Main.jsx
I have used NavLink
on two "Button" components for Login
and Signup
to the above respective routes. The Buttons have handleClick
function which applies a class called "invisible"
to the two divs mentioned below which sets the display property to none using conditional rendering to hide the divs and only render the <Outlet />
(Login
or the SignUp
component).
But when you try to go to back to the "/"
route using the browser back button the divs are still invisible and the page need to be reloaded in order for it to be visible.
App.jsx
import React, { useState } from "react";
import Main from "./Main";
import SignUp from "./SignUp";
import Login from "./Login";
import Home from "./Home";
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider,} from "react-router-dom";
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<Main />}>
<Route path="login" element={<Login />} />
<Route path="signup" element={<SignUp />} />
</Route>
)
);
function App() {
return <RouterProvider router={router} />;
}
export default App;
Main.jsx
import React, { useState } from "react";
import Button from "./Button";
import { NavLink, Outlet } from "react-router-dom";
function Main() {
const [isVisible, setIsVisible] = useState(true);
const handleClick = () => {
setIsVisible(false);
};
return (
<div className="main-div">
<div className={`main-heading-div ${isVisible ? "" : "invisible"}`}>
<p className="main-heading">
Welcome to <span>The Book Keeper</span>
</p>
<p>Your Personal Library, Perfectly Organized</p>
</div>
<div className={`button-div ${isVisible ? "" : "invisible"}`}>
<NavLink to="/login">
<Button text="Log in" name="main-login" onClick={handleClick} />
</NavLink>
<NavLink to="/signup">
<Button text="Sign Up" name="main-signup" onClick={handleClick} />
</NavLink>
</div>
<Outlet />
</div>
);
}
export default Main;
This problem arose when I tried to solve a previous problem of, the result of the <Outlet />
overlapping with with contents of the Main
component when any of the NavLink
where clicked. So I tried to solve this by used useState
+ css and then arrived at this issue.
To reset the isVisible
state back to true
when the user navigates to the "/"
root route you could use the useMatch
and useEffect
hooks to check for that match explicitly and reset the state.
Example:
import { NavLink, Outlet, useMatch } from 'react-router-dom';
function Main() {
const [isVisible, setIsVisible] = useState(true);
const homeMatch = useMatch("/");
useEffect(() => {
if (homeMatch) {
setIsVisible(true);
}
}, [homeMatch, setIsVisible]);
const handleClick = () => {
setIsVisible(false);
};
...
}
Of course, if all you are really trying to accomplish is for the Main
component content to only be rendered on "/"
then it might be more advisable to refactor that into an index route component.
Example:
const MainPage = () => (
<>
<div className="main-heading-div">
<p className="main-heading">
Welcome to <span>The Book Keeper</span>
</p>
<p>Your Personal Library, Perfectly Organized</p>
</div>
<div className="button-div">
<NavLink to="/login">
<Button text="Log in" name="main-login" />
</NavLink>
<NavLink to="/signup">
<Button text="Sign Up" name="main-signup" />
</NavLink>
</div>
</>
);
function Main() {
return (
<div className="main-div">
<Outlet />
</div>
);
}
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<Main />}>
<Route index element={<MainPage />} />
<Route path="login" element={<Login />} />
<Route path="signup" element={<SignUp />} />
</Route>
)
);