Restore original page when navigating back after history.pushState
You need to watch the current address for changes and react to it yourself.
See this example:
https://developer.mozilla.org/en/DOM/window.onpopstate
Also have a look at the documentation:
https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history/
React, Single Page Apps, and the Browser's back button
Yes, it is very much possible to switch routes while keeping the DOM rendered, but hidden!
If you are building a SPA, it would be a good idea to use client side routing. This makes your task easy:
For hiding, while keeping components in the DOM, use either of the following css:
.hidden { visibility: hidden }
only hides the unused component/route, but still keeps its layout..no-display { display: none }
hides the unused component/route, including its layout.
For routing, using react-router-dom
, you can use the function children prop on a Route
component:
children: func
Sometimes you need to render whether the path matches
the location or not. In these cases, you can use the function children
prop. It works exactly like render except that it gets called whether
there is a match or not.The children render prop receives all the same
route props as the component and render methods, except when a route
fails to match the URL, then match is null. This allows you to
dynamically adjust your UI based on whether or not the route matches.
Here in our case, I'm adding the hiding css classes if the route doesn't match:
App.tsx:
export default function App() {
return (
<div className="App">
<Router>
<HiddenRoutes hiddenClass="hidden" />
<HiddenRoutes hiddenClass="no-display" />
</Router>
</div>
);
}
const HiddenRoutes: FC<{ hiddenClass: string }> = ({ hiddenClass }) => {
return (
<div>
<nav>
<NavLink to="/1">to 1</NavLink>
<NavLink to="/2">to 2</NavLink>
<NavLink to="/3">to 3</NavLink>
</nav>
<ol>
<Route
path="/1"
children={({ match }) => (
<li className={!!match ? "" : hiddenClass}>item 1</li>
)}
/>
<Route
path="/2"
children={({ match }) => (
<li className={!!match ? "" : hiddenClass}>item 2</li>
)}
/>
<Route
path="/3"
children={({ match }) => (
<li className={!!match ? "" : hiddenClass}>item 3</li>
)}
/>
</ol>
</div>
);
};
styles.css:
.hidden {
visibility: hidden;
}
.no-display {
display: none;
}
Working CodeSandbox: https://codesandbox.io/s/hidden-routes-4mp6c?file=/src/App.tsx
Compare the different behaviours of visibility: hidden
vs. display: none
.
Note that in both cases, all of the components are still mounted to the DOM!
You can verify with the inspect tool in the browser's dev-tools.
Reusable solution
For a reusable solution, you can create a reusable HiddenRoute component.
In the following example, I use the hook useRouteMatch
, similar to how the children
Route prop works. Based on the match, I provide the hidden class to the new components children:
import "./styles.css";
import {
BrowserRouter as Router,
NavLink,
useRouteMatch,
RouteProps
} from "react-router-dom";
// Reusable components that keeps it's children in the DOM
const HiddenRoute = (props: RouteProps) => {
const match = useRouteMatch(props);
return <span className={match ? "" : "no-display"}>{props.children}</span>;
};
export default function App() {
return (
<div className="App">
<Router>
<nav>
<NavLink to="/1">to 1</NavLink>
<NavLink to="/2">to 2</NavLink>
<NavLink to="/3">to 3</NavLink>
</nav>
<ol>
<HiddenRoute path="/1">
<li>item 1</li>
</HiddenRoute>
<HiddenRoute path="/2">
<li>item 2</li>
</HiddenRoute>
<HiddenRoute path="/3">
<li>item 3</li>
</HiddenRoute>
</ol>
</Router>
</div>
);
}
Working CodeSandbox for the reusable solution: https://codesandbox.io/s/hidden-routes-2-3v22n?file=/src/App.tsx
React history.push() is updating url but not navigating to it in browser
Check if you don't have nested BrowserRouter tags.
I had this issue on react-router v4 but I solved it after changing the app to only have the BrowserRouter at the top most level like the example below.
ReactDOM.render(
<BrowserRouter >
<App />
</BrowserRouter>,
document.getElementById('root')
);
Related Topics
Optimum Way to Compare Strings in JavaScript
React Router with Optional Path Parameter
What Is the Most Efficient Way to Concatenate N Arrays
How Does Shallow Compare Work in React
Password Encryption at Client Side
Why Does a Form with One Text Input Submit on Enter While One with Two Text Inputs Does Not
Why Is the Variable Holding the Input Value Always Logged as Empty
Uncaught Referenceerror: $ Is Not Defined Error in Jquery
Fade Background Image in and Out with Jquery
JavaScript - .Innerhtml Changes Auto Close Tags
Prevent Safari Loading from Cache When Back Button Is Clicked
How to Use Jquery in Chrome Extension
How to Stop Event Bubbling on Checkbox Click
Return Positions of a Regex Match() in JavaScript
Why Use Jquery On() Instead of Click()
Has Facebook Sharer.PHP Changed to No Longer Accept Detailed Parameters
"Invocation Context" and "Execution Context" in JavaScript: Are We Talking of the Same Thing