useUrlState
A hook alike useLayoutEffect but skips running the effect for the first time.
Overview
A hook alike useLayoutEffect but skips running the effect for the first time.
Installation
Open inpnpm dlx shadcn@latest add https://shadcn-ahooks.vercel.app/r/useUrlState.jsonnpx shadcn@latest add https://shadcn-ahooks.vercel.app/r/useUrlState.jsonyarn shadcn@latest add https://shadcn-ahooks.vercel.app/r/useUrlState.jsonbun shadcn@latest add https://shadcn-ahooks.vercel.app/r/useUrlState.jsonExamples
This hook relies on useLocation & useHistory & useNavigate from
react-router, to use this hook, you need to ensure1. Your project is using
react-routerversion 5.0 or 6.0 to manage routing2. Installed @ahooksjs/use-url-state
Usage
import useUrlState from '@/src/hooks/ahooks/useUrlState';Examples
CodeSandbox Demo
React Router V5: https://codesandbox.io/s/suspicious-feather-cz4e0?file=/App.tsx
React Router V6: https://codesandbox.io/s/autumn-shape-odrt9?file=/App.tsx
Default usage
import React from 'react';
import useUrlState from '@/src/hooks/ahooks/useUrlState';
export default () => {
const [state, setState] = useUrlState({ count: '1' });
return (
<>
<button
style={{ marginRight: 8 }}
type="button"
onClick={() => setState({ count: Number(state.count || 0) + 1 })}
>
add
</button>
<button type="button" onClick={() => setState({ count: undefined })}>
clear
</button>
<div>state: {state?.count}</div>
</>
);
};Multi-state management
import React from 'react';
import useUrlState from '@/src/hooks/ahooks/useUrlState';
export default () => {
const [state, setState] = useUrlState({ page: '1', pageSize: '10' });
return (
<>
<div>
page: {state.page}
<span style={{ paddingLeft: 8 }}>
<button
onClick={() => {
setState((s) => ({ page: Number(s.page) + 1 }));
}}
>
+
</button>
<button
onClick={() => {
setState((s) => ({ page: Number(s.page) - 1 }));
}}
style={{ margin: '0 8px' }}
>
-
</button>
<button
onClick={() => {
setState({ page: undefined });
}}
>
reset
</button>
</span>
</div>
<br />
<div>
pageSize: {state.pageSize}
<span style={{ paddingLeft: 8 }}>
<button
onClick={() => {
setState((s) => ({ pageSize: Number(s.pageSize) + 1 }));
}}
>
+
</button>
<button
onClick={() => {
setState((s) => ({ pageSize: Number(s.pageSize) - 1 }));
}}
style={{ margin: '0 8px' }}
>
-
</button>
<button
onClick={() => {
setState({ pageSize: undefined });
}}
>
reset
</button>
</span>
</div>
</>
);
};Multi-state management (split)
import React from 'react';
import useUrlState from '@/src/hooks/ahooks/useUrlState';
export default () => {
const [page, setPage] = useUrlState({ page: '1' });
const [pageSize, setPageSize] = useUrlState({ pageSize: '10' });
return (
<>
<div>
page: {page.page}
<span style={{ paddingLeft: 8 }}>
<button
onClick={() => {
setPage((s) => ({ page: Number(s.page) + 1 }));
}}
>
+
</button>
<button
onClick={() => {
setPage((s) => ({ page: Number(s.page) - 1 }));
}}
style={{ margin: '0 8px' }}
>
-
</button>
<button
onClick={() => {
setPage({ page: undefined });
}}
>
reset
</button>
</span>
</div>
<br />
<div>
pageSize: {pageSize.pageSize}
<span style={{ paddingLeft: 8 }}>
<button
onClick={() => {
setPageSize((s) => ({ pageSize: Number(s.pageSize) + 1 }));
}}
>
+
</button>
<button
onClick={() => {
setPageSize((s) => ({ pageSize: Number(s.pageSize) - 1 }));
}}
style={{ margin: '0 8px' }}
>
-
</button>
<button
onClick={() => {
setPageSize({ pageSize: undefined });
}}
>
reset
</button>
</span>
</div>
<div>
<button
onClick={async () => {
await setPageSize({ pageSize: undefined });
await setPage({ page: undefined });
}}
>
reset all
</button>
</div>
</>
);
};Custom query-string options
import React from 'react';
import useUrlState from '@/src/hooks/ahooks/useUrlState';
export default () => {
const [state, setState] = useUrlState(
{ ids: ['1', '2', '3'] },
{
parseOptions: {
arrayFormat: 'comma',
},
stringifyOptions: {
arrayFormat: 'comma',
},
},
);
return (
<div>
<button
onClick={() => {
const arr = Array(3)
.fill(1)
.map(() => Math.floor(Math.random() * 10));
setState({ ids: arr });
}}
>
变更数组state
</button>
<div>ids: {JSON.stringify(state.ids)}</div>
</div>
);
};API
const [state, setState] = useUrlState(baseState, options);Params
| Property | Description | Type | Default |
|---|---|---|---|
| baseState | URL search params will be merged into BaseState | S | () => S | - |
| options | Url config | Options | - |
Options
| Property | Description | Type | Default |
|---|---|---|---|
| navigateMode | Type of history navigate mode | 'push' | 'replace' | 'push' |
| parseOptions | parse options of query-string | ParseOptions | - |
| stringifyOptions | stringify options of query-string | StringifyOptions | - |
Result
| Property | Description | Type |
|---|---|---|
| state | Url query object | object |
| setState | Same as useState, but state should be object | (state: S) => void | (() => ((state: S) => S)) |