Last active
December 27, 2022 07:36
Star
You must be signed in to star a gist
React Hook recipe from https://usehooks.com
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useMemo } from "react"; | |
import { useParams, useLocation, useHistory, useRouteMatch } from 'react-router-dom'; | |
import queryString from 'query-string'; | |
// Usage | |
function MyComponent(){ | |
// Get the router object | |
const router = useRouter(); | |
// Get value from query string (?postId=123) or route param (/:postId) | |
console.log(router.query.postId); | |
// Get current pathname | |
console.log(router.pathname) | |
// Navigate with with router.push() | |
return ( | |
<button onClick={(e) => router.push('/about')}>About</button> | |
); | |
} | |
// Hook | |
export function useRouter() { | |
const params = useParams(); | |
const location = useLocation(); | |
const history = useHistory(); | |
const match = useRouteMatch(); | |
// 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]); | |
} |
@Simply1993 The result would be the same if you used the useHistory hook directly right? useRouter doesn't cause any re-renders itself because it doesn't set state. To the degree that there are re-renders and new object references are returned, that's a decision made by the underlying React Router hooks (or a bug that should be reported with them).
Cannot find name 'queryString'.ts(2304)
what can i do with this?
react-router-dom is on its version 6, i'd suggest to adapt to this version
react-router-dom is on its new version 6.4, i'd suggest to adapt to this version.
@gragland I updated the hook with the react-router-dom latest version 6.
import { useMemo } from "react";
import {
useParams,
useLocation,
useNavigate,
useSearchParams,
} from "react-router-dom";
// Usage
function MyComponent() {
// Get the router object
const router = useRouter();
// Get value from query string (?postId=123) or route param (/:postId)
console.log(router.query.postId);
// Get current pathname
console.log(router.pathname);
// Navigate with router.navigate()
return <button onClick={(e) => router.navigate("/about")}>About</button>;
}
export function useRouter() {
const params = useParams();
const location = useLocation();
const [searchParams] = useSearchParams();
const navigate = useNavigate();
let queryObj = {};
for (const [key, value] of searchParams.entries()) {
queryObj[key] = value;
}
// Return our custom router object
// Memoize so that a new object is only returned if something changes
return useMemo(() => {
return {
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: {
...params,
...queryObj,
},
// Include location, navigate objects so we have
// access to extra React Router functionality if needed.
location,
navigate,
};
}, [params, location, navigate]);
}
export default MyComponent;
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I said:
As far as I know, useMemo does not check equal for deep objects.
So you have to do something like this: