mirror of
https://github.com/rjNemo/React-SaaS-sample
synced 2026-06-06 05:06:38 +00:00
86 lines
2.6 KiB
JavaScript
86 lines
2.6 KiB
JavaScript
/*
|
|
A wrapper around React Router that adds a useRouter() hook so that any component
|
|
can easily access params, location, history, and trigger navigation.
|
|
Import from this file instead of react-router-dom directly.
|
|
*/
|
|
|
|
import React, { useMemo, useEffect } from "react";
|
|
import {
|
|
Router as RouterOriginal,
|
|
useParams,
|
|
useLocation,
|
|
useNavigate,
|
|
useMatch
|
|
} from "react-router-dom";
|
|
import queryString from "query-string";
|
|
|
|
// Use a custom history object and pass to Router so that we
|
|
// can utilize history.listen() where needed (such as for pageview tracking)
|
|
import { createBrowserHistory } from "history";
|
|
export const history = createBrowserHistory();
|
|
|
|
// Export our <Router> component
|
|
// Includes custom history object and component for auto-scrolling to top
|
|
export function Router({ children }) {
|
|
return (
|
|
<RouterOriginal history={history}>
|
|
<ScrollToTop />
|
|
{children}
|
|
</RouterOriginal>
|
|
);
|
|
}
|
|
|
|
// Custom useRouter hook for getting route data and methods inside any component.
|
|
// NOTE: This hook includes all React Router hooks, which can result in extra re-renders
|
|
// in some cases. When needed, you can optimize performance by importing the specific hook
|
|
// you need (such as useParams or useLocation) instead of this custom useRouter hook.
|
|
export function useRouter() {
|
|
const params = useParams();
|
|
const location = useLocation();
|
|
const history = useNavigate();
|
|
const match = useMatch();
|
|
|
|
// Return our custom router object
|
|
// Memoize so that a new object is only returned if something changes
|
|
return useMemo(() => {
|
|
return {
|
|
// For convenience add push(), replace(), pathname at top level
|
|
push: history.push,
|
|
replace: history.replace,
|
|
pathname: location.pathname,
|
|
// Merge params and parsed query string into single "query" object
|
|
// so that they can be used interchangeably.
|
|
// Example: /:topic?sort=popular -> { topic: "react", sort: "popular" }
|
|
query: {
|
|
...queryString.parse(location.search), // Convert string to object
|
|
...params
|
|
},
|
|
// Include match, location, history objects so we have
|
|
// access to extra React Router functionality if needed.
|
|
match,
|
|
location,
|
|
history
|
|
};
|
|
}, [params, match, location, history]);
|
|
}
|
|
|
|
// Remove or customize if you need more advanced scroll behavior
|
|
// and don't want to always scroll to top when location.pathname changes.
|
|
function ScrollToTop() {
|
|
const location = useLocation();
|
|
useEffect(() => {
|
|
window.scrollTo(0, 0);
|
|
}, [location.pathname]);
|
|
return null;
|
|
}
|
|
|
|
export {
|
|
Route,
|
|
Routes,
|
|
Link,
|
|
NavLink,
|
|
useParams,
|
|
useLocation,
|
|
useNavigate,
|
|
useMatch
|
|
} from "react-router-dom";
|