In JavaScript, How to "Clear" the Back (History -1)

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:

  1. .hidden { visibility: hidden } only hides the unused component/route, but still keeps its layout.

  2. .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



Leave a reply



Submit