next-batch-router
Version:
An alternative to next/router that batches push and replace calls. It allows for multiple pushes without overwriting each other.
127 lines (88 loc) • 4.93 kB
Markdown
# next-batch-router
[](https://www.npmjs.com/package/next-batch-router)
[](https://bundlephobia.com/package/next-batch-router)
[](https://github.com/youha-info/next-batch-router/blob/main/LICENSE)
An alternative to `useRouter` hook in `next/router` that batches `push` and `replace` calls.
It allows for multiple `push` without overwriting each other.
## Why do I need it?
With `next/router`, the code below doesn't work.
We expect query string to result in `?a=1&b=2`, but it results in `?a=1` or `?b=2`
```js
const router = useRouter();
const onClick = () => {
router.push({ query: { ...router.query, a: 1 } });
router.push({ query: { ...router.query, b: 2 } });
};
```
❌ Results in `?a=1` or `?b=2`
<br/>
By using `useBatchRouter`, calls to `push` are queued and merged together.
```js
const batchRouter = useBatchRouter();
const onClick = () => {
batchRouter.push({ query: { a: 1 } });
batchRouter.push({ query: { b: 2 } });
};
```
✅ Results in `?a=1&b=2`
## Installation
```sh
$ yarn add next-batch-router
or
$ npm install next-batch-router
```
## Usage
### 1. BatchRouterProvider
Set up `<BatchRouterProvider/>` at the top of the component tree, preferably inside pages/\_app.js
```js
import { BatchRouterProvider } from "next-batch-router";
const MyApp = ({ Component, pageProps }) => (
<BatchRouterProvider>
<Component {...pageProps} />
</BatchRouterProvider>
);
```
### 2. useBatchRouter
Instead of using `useRouter` from `next/router`, use `useBatchRouter` instead.
```js
import { useBatchRouter } from "next-batch-router";
const Component = () => {
const batchRouter = useBatchRouter();
const onClick = () => {
batchRouter.push({ query: { a: 1 } });
batchRouter.push({ query: { b: 2 } });
};
return (
<div>
<button onClick={onClick}>Click me!</button>
</div>
);
};
```
### Definition
```js
batchRouter.push(url, as, options);
batchRouter.replace(url, as, options);
```
`url`: { query?: SetQueryAction, hash?: string | null }
- You cannot put `string`. Only `object` with `query` and `hash` property is allowed.
- `query` is similar to the original `query` parameter with some differences.
1. Original `push` completely replaced the query string with the given object, but `batchRouter.push` merges the object by default.
2. `null` value removes the query parameter from the query string. Calling `batchRouter.push({query: {a: null}})` on `?a=1&b=2` results in `?b=2`.
3. `undefined` value is ignored. Calling `batchRouter.push({query: {a: undefined}})` on `?a=1&b=2` results in `?a=1&b=2`.
4. You can put a `function` instead of an `object` as a `query` parameter, similar to `React.useState`. However, the returned object is not merged automatically and must be merged manually within the function. Since merge is not automatically done, the `undefined` value is handled as `null` and is removed from the query string.
- `hash` is the "hash" part from `?param=foo#hash` url. It's similar to the original `hash` parameter with some differences.
1. Originally, `hash` was not preserved unless provided in the `router.push` call. `batchRouter.push` preserves the original hash if not supplied.
2. `null` value removes the hash.
3. When multiple `push` calls have a `hash` parameter, the last one is applied.
4. There is a bug in which removing all query parameters doesn't work if there is a hash in the URL. Such as this: `batchRouter.push({ query: ()=>({}), hash:"hash" })`
`as`?: { query?: SetQueryAction, hash?: string | null }
- Optional. Defines how the browser URL bar will look like. Can be used to set param in router.query but hide it from the URL. Check [next/router documentation](https://nextjs.org/docs/api-reference/next/router#routerpush) for more detail. Similar to `url`.
`options`?: { scroll?: boolean, shallow?: boolean, locale?: string }
- `scroll`: Scroll to the top of the page after navigation. Defaults to `true`. When multiple `push` and `replace` calls are merged, all must have `scroll: false` to not scroll after navigation.
- `shallow`: Update the path of the current page without rerunning `getStaticProps`, `getServerSideProps` or `getInitialProps`. Defaults to `false`. When merged, all must have `shallow: true` to do shallow routing.
- `locale`: Indicates locale of the new page. When merged, the last one will be applied.
## Limitations
`useBatchRouter` is currently not designed to replace `useRouter`. It's to be used together and `useBatchRouter` should be used for changing only the query and hash part of the URL.
## License
This project is licensed under the MIT License.