🇺🇦 Support Ukraine 🇺🇦 Help Provide Humanitarian Aid to Ukraine.
Geschichte
(german for History / Story / Tale) Let's you manage query-parameters with hooks.
Uses immer
and zustand
to manage the internal state.
Documentation & Demo: https://bowlingx.github.io/geschichte/index.html
API: https://bowlingx.github.io/geschichte/api/index.html
yarn add geschichte
npm install geschichte
import { pm, factoryParameters, serializers } from 'geschichte'
import { GeschichteWithHistory } from 'geschichte/historyjs'
import { createBrowserHistory } from 'history'
const parameterConfig = {
item: pm(
'queryParameter',
serializers.string /** a basic collection of serializers is availble, like date, int, float, arrays */,
(value?: V, initialValue?: V) =>
boolean /** define an optional skip function which will determine if the parameter will be included in the url or not */
),
/* ... more keys, any depth. */
}
// default value is either an object or a factory () => defaultValue
const defaultValue = {
item: 'defaultValue' /** it automatically skips null or default values*/,
}
// exports a hook (`useQuery`), and
// utility methods `createQueryString` that let's you create a query string based on the described object anywhere outside of components etc.
// `parseQueryString` let's you parse a query string into an object as defined in the `parameterConfig`.
const { useQuery, createQueryString, parseQueryString } = factoryParameters(
parameterConfig,
defaultValue /** optional namespace, (creates a prefix separated by a dot)*/
)
const Component = () => {
const {
values,
pushState,
replaceState,
resetPush,
resetReplace,
createQueryString,
batchReplaceState,
batchPushState,
} = useQuery()
return (
<>
<button
onClick={() => pushState((values) => void (values.item = 'newValue'))}
>
push new state
</button>
<button
onClick={() =>
replaceState((values) => void (values.item = 'anotherOne'))
}
>
replace state
</button>
<button onClick={resetPush}>reset (push) to defaults</button>
<button onClick={resetReplace}>reset (replace) to defaults</button>
<div>{JSON.stringify(values)}</div>
<div>The current queryString: {createQueryString()}</div>
</>
)
}
const App = () => (
<GeschichteWithHistory history={createBrowserHistory()}>
<Component />
</GeschichteWithHistory>
)
Geschichte
let's you describe and serialize an arbitrary object of any depth to your browsers query and history.
It takes care of updating the next state and current query in a efficient way using immerjs
.
It works on both the browser and server side (with createMemoryHistory
)
I was inspired by immer
and zustand
, so I picked a fitting german name :).
- Add more tests
- Propper examples and documentation of the full API
- Describe Use-Cases
It works out of the box with react-router (by providing the same history
instance).
Nextjs support is build in, but requires a different Adapter.
/** _app.tsx */
import React, { memo } from 'react'
import GeschichteForNextjs from 'geschichte/nextjs'
import type { AppProps } from 'next/app'
function App({ Component, pageProps }: AppProps) {
return (
<GeschichteForNextjs>
<Component {...pageProps} />
</GeschichteForNextjs>
)
}
export default memo(App)
You can use Geschichte
with the app router as well (from nextjs
13).
/** page.tsx */
import Geschichte from 'geschichte/nextjs-app-router'
import MoreComponentsWithClientSideState from '@/components/ClientComponents'
export default function Home() {
return (
<main>
<header>My header</header>
<Geschichte>
<MoreComponentsWithClientSideState />
</Geschichte>
<footer>My footer</footer>
</main>
)
}