Package Exports
- state-in-url
Readme
state-in-url
Features
- Seamless state synchronization with URL query parameters.
- Preserves shape and types of data
- Full TypeScript support for enhanced developer experience.
- Automatic serialization and deserialization of complex objects.
- Separate hooks for Next.js (useUrlState) and React.js (useUrlEncode) usage.
- Efficient updates with minimal re-renders.
- Lightweight, no dependencies.
Table of content
- Installation
- Usage with Next.js
- Usage with React.js
- Low-level encode/decode functions
- Gothas
- Contact & Support
- Changelog
- License
installation
# npm
npm install --save state-in-url
# yarn
yarn add state-in-url
# pnpm
pnpm add state-in-url
useUrlState hook for Next.js
useUrlState
is a custom React hook for Next.js applications that manages state in the URL query string. It allows you to store and retrieve state from the URL search parameters, providing a way to persist state across page reloads and share application state via URLs.
Usage examples
Basic
'use client'
import { useUrlState } from 'state-in-url';
// State shape should be stored in a constant, don't pass an object directly
const countState = { count: 0 };
function MyComponent() {
const { state, updateState, updateUrl } = useUrlState(countState);
// won't let you to accidently mutate state directly, requires TS
// state.count = 2 // <- error
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => updateUrl({ count: state.count + 1 })}>
Increment (Update URL)
</button>
<button onClick={() => updateState({ count: state.count + 1 })}>
Increment (Local Only)
</button>
<button onClick={() => updateUrl(state)}>
Sync changes to url
</button>
</div>
)
}
With complex state shape
'use client'
import { useUrlState } from 'state-in-url';
interface UserSettings {
theme: 'light' | 'dark';
fontSize: number;
notifications: boolean;
}
const defaultSettings: UserSettings {
theme: 'light',
fontSize: 16,
notifications: true,
}
function SettingsComponent() {
// `state` will infer from UserSettings type!
const { state, updateUrl } = useUrlState(defaultSettings);
const toggleTheme = () => {
updateUrl(current => ({
...current,
theme: current.theme === 'light' ? 'dark' : 'light',
}));
};
return (
<div>
<h2>User Settings</h2>
<p>Theme: {state.theme}</p>
<p>Font Size: {state.fontSize}px</p>
<button onClick={toggleTheme}>Toggle Theme</button>
{/* Other UI elements to update other settings */}
</div>
);
}
...
// Other component
function Component() {
const { state } = useUrlState(defaultSettings);
return (
<div>
<p>Notifications is {state.notifications ? 'On' : 'Off'}</p>
</div>
)
}
With arbitrary state shape (not recommended)
'use client'
import { useUrlState } from 'state-in-url';
const someObj = {};
function SettingsComponent() {
const { state, updateUrl, updateState } = useUrlState<object>(someObj);
}
useUrlEncode hook for React.js
useUrlEncode
is a custom React hook that provides utility functions for encoding and decoding state to and from URL search parameters. This hook doesn't depend on Nextjs, and will works with any React application.
Accepts optional defaultState
argument.
import { useUrlEncode } from 'state-in-url';
const Component = () => {
const { parse, stringify } = useUrlEncode();
const str = stringify({ age: 36 }); // age=∓36
const obj = parse(str); // { age: 36 }
const currentParams = parse(window.location.search);
// OR
// const obj = parse(new URLSearchParams(window.location.search))
const updateSearch = () => {
const currentParams = new URLSearchParams(window.location.search);
const newState = { query: 'react hooks', page: 2 };
const updatedParamsString = stringify(newState, currentParams);
console.log(updatedParamsString);
// Output: existing params + query=react%20hooks&page=2
};
}
encode
and decode
helpers
There low level helpers to stringify and parse query string params. Useful for other frameworks or pure JS.
import { encode, decode } from 'state-in-url';
const state = { obj: [1, 2, 3], obj2: true }
// to params
const params = new URLSearchParams();
Object.entries(state).forEach(([key, value]) => {
params.set(key, encode(value));
});
// from params
const obj = Object.fromEntries(
[...params.entries()].map(([key, value]) => [
key,
decode(value),
]),
)
Gothas
- Can pass only serializable values,
Function
,BigInt
orSymbol
won't work, probably things likeArrayBuffer
neither. But won't throw an error if you do it accidently. - Developed and tested with recent
Next.js
andTypescript
versions.
Contact & Support
- Create a GitHub issue for bug reports, feature requests, or questions
- Add a ⭐️ star on GitHub to support the project!
Changelog
License
This project is licensed under the MIT license.