Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
react-router-query-hooks
Advanced tools
A small package that augments the basic react-router-dom
hooks (useLocation
and useHistory
) to be more query string aware by parsing using the query-string
library.
Primarily, it exports a simple useQueryParams
hook for reading and manipulating the URL query string (useful for UIs where sort order, or page number is encoded in the URL). See the usage notes for more details.
Depends on:
query-string
react-router-dom@^5.1
or greater (needs router hooks)This package is also written in ES6, so to use, you'll need some transpiler such as babel to run on node_modules.
$ npm install react-router-query-hooks react-router-dom
or
$ yarn add react-router-query-hooks react-router-dom
There are two main uses for this package:
useQueryParams
hook.useLocation
or useHistory
: useLocationWithQuery
and useHistoryWithQuery
.Note: With both usages, you'll need to have your components wrapped in a Router
(any flavor exported by React Router should work).
useQueryParams
HookThe easiest way to use this library is to use the higher-level useQueryParams
hook. It's useful for reading or updating the current query parameters from the URL. Behind the scenes, it's basically a sweetened version of the useHistoryWithQuery
hook outlined in the next section.
import { useQueryParams } from "react-router-query-hooks";
const MyComponentInRouter = () => {
const [query, { pushQuery, replaceQuery }] = useQueryParams();
};
The return value for the useQueryParams
hook is similar to React's useState
; however it includes two setters instead of one: pushQuery
and replaceQuery
—to either add a history entry or replace the current history entry respectively. In the above example the first entry in the tuple (query
) contains the parsed query parameters from the URL.
useLocation
and useHistory
hooksIf you want to use some more primitive hooks, the useQueryParams hook builds upon the two hooks that wrap the underlying React Router hooks (useLocation, and useHistory).
useLocationWithQuery
This modified hook adds the query
key to React Router's location
object which contains a parsed version of location.search
. As with useLocation
it is read-only (has no setters).
import { useLocation } from "react-router-dom";
import { useLocationWithQuery } from "react-router-query-hooks";
const MyComponentInRouter = () => {
// const location = useLocation();
const location = useLocationWithQuery(); // Same interface as above but with location.query
/* Augmented location object:
{
key: 'ac3df4', // not with HashHistory!
pathname: '/somewhere',
search: '?some=search-string',
query: {
some: "search-string" // <- ADDED PROPERTY
},
hash: '#howdy',
state: {
[userDefined]: true
}
}
*/
};
useHistoryWithQuery
This modified hook builds upon React Router's history
object and the above location additions:
history.location
, it adds the query
key to React Router's location
object (as above)query
key. So history.replace
supports both paths (as before) and location objects with the query
key.history.location
when the location changes. While the internal history object is updated, this is a mutation, and React will not update the component. You must listen to the location separately using useLocationWithQuery
or the combined useQueryParams
to update the component upon a location change.import { useHistory } from "react-router-dom";
import { useLocationWithQuery } from "react-router-query-hooks";
const MyComponentInRouter = () => {
// const history = useHistory();
const history = useHistoryWithQuery();
// Supports push & replace with query object in location (along with supporting the existing API):
return (
<>
<button onClick={() => history.replace({ query: { page: 1 } })}>
Go to Page 1
</button>
<button onClick={() => history.push({ query: { page: 1 } })}>
Go to Page 1
</button>
</>
);
};
The motivation for this package was to have an easy way to maintain URL query parameters, that was simple, somewhat light, and used the URL as the source of truth. Furthermore, it was designed to support UIs that have pagination:
import React from "react";
import { useQueryParams } from "react-router-query-hooks";
const MyComponentInRouter = () => {
const [query, { replaceQuery }] = useQueryParams();
const { page, sortBy, order } = query;
// Useful for calling APIs with a page and sort order
const { data } = useAPI("/my-resource", { page, sortBy, order });
return (
<div>
<Table
data={data}
onHeaderClick={(sortBy, order) =>
replaceQuery({ ...query, sortBy, order })
}
/>
<Pagination onClick={page => replaceQuery({ ...query, page })} />
</div>
);
};
Sometimes you don't want to recreate a callback on every render. Consider the example above: on each render, onHeaderClick
callback is redefined. The next optimization (if needed) is to wrap that callback in useCallback
:
import React, { useCallback } from "react";
import { useQueryParams } from "react-router-query-hooks";
const MyComponentInRouter = () => {
const [query, { replaceQuery }] = useQueryParams();
const { page, sortBy, order } = query;
// Useful for calling APIs with a page and sort order
const { data } = useAPI("/my-resource", { page, sortBy, order });
const onClick = useCallback(
(sortBy, order) => replaceQuery({ ...query, sortBy, order }),
[query]
);
return (
<div>
<Table data={data} onHeaderClick={onClick} />
<Pagination onClick={page => replaceQuery({ ...query, page })} />
</div>
);
};
That's a good start: on each render we'll use the same onClick
callback and only redefine if query
changes. In some cases, query may change frequently. The next optimization we can make is to update using a function (this should look familiar when using useState
):
const onClick = useCallback(
(sortBy, order) =>
replaceQuery(currentQuery => ({ ...currentQuery, sortBy, order })),
[]
);
Now, our callback doesn't have any dependencies, and will be reused for each render! This method of changing the state works for both replaceQuery
and pushQuery
.
FAQs
React Router hooks with query string parsing
The npm package react-router-query-hooks receives a total of 10 weekly downloads. As such, react-router-query-hooks popularity was classified as not popular.
We found that react-router-query-hooks demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.