State hooks are only available in descendant components of <LocationStateProvider>
.
type LocationStateDefinition<
T,
StoreName extends string = "session" | "url",
> = {
name: string;
defaultValue: T;
storeName: StoreName;
refine?: Refine<T>;
};
Common options for state hooks.
Warning State hooks evaluates this option only once at the first rendering. Passing different values at re-rendering is not applied.
T
: Type of state.StoreName
: The type of theStore
name.
name
: A unique name that identifies the state at the current history location in theStore
specified bystoreName
.defaultValue
: Default value returned by state hooks if there is no state in theStore
.storeName
: The name of theStore
where the state will be stored. By default,"session"
and"url"
are available. You can be changed with the type parameterStoreName
.refine?
: Function to validate and/or convert a state retrieved from theStore
. See Refine.
const counter: LocationStateDefinition<number> = {
name: "count",
defaultValue: 0,
storeName: "session",
};
const [count, setCount] = useLocationValue(counter);
type Refine<T> = (state: unknown) => T | undefined;
The type of the function that validate and/or convert the state retrieved from the Store
. It must not throw an error if validation fails.
T
: Type of state.
state
: The value retrieved from store.
Validated state value, converted from it, or undefined. If undefined
is returned, state hooks will return the defaultValue
of the LocationStateDefinition
as state.
const zodRefine =
<T extends unknown>(schema: ZodType<T>): Refine<T> =>
(value) => {
const result = schema.safeParse(value);
return result.success ? result.data : undefined;
};
const [counter, setCounter] = useLocationState({
name: "counter",
defaultValue: 0,
storeName,
refine: zodRefine(
// Migration of state that were previously type `string`, but are now type `number`.
z.union([
z.number(),
z
.string()
.regex(/\d+/)
.transform((v) => Number(v)),
]),
),
});
type SetState<T> = (valueOrUpdater: T | ((prev: T) => T)) => void;
declare const useLocationState: <T>(
definition: LocationStateDefinition<T, DefaultStoreName>,
) => [T, SetState<T>];
Allows access to the state associated with the current history location from a specified Store
. This hook subscribes to re-render the component if there is a change in the state.
T
: Type of state.
definition
: SeeLocationStateDefinition
.
Returns an array that first element is a state and the second element is a state update function.
const [count, setCount] = useLocationState({
name: "count",
defaultValue: 0,
storeName: "session",
});
declare const useLocationStateValue: <T>(
definition: LocationStateDefinition<T, DefaultStoreName>,
) => T;
Allows a reference to the state associated with the current history location from a specified Store
. This hook subscribes to re-render the component if there is a change in the state.
T
: Type of state.
definition
: SeeLocationStateDefinition
.
Returns state.
const count = useLocationStateValue({
name: "count",
defaultValue: 0,
storeName: "session",
});
type GetState<T> = () => T;
declare const useLocationGetState: <T>(
definition: LocationStateDefinition<T, DefaultStoreName>,
) => GetState<T>;
Allows getting of the state associated with the current history location from a specified Store
. This hooks will not re-render the component if there is a change in the state.
T
: Type of state.
definition
: SeeLocationStateDefinition
.
Returns the callback function to get state. It can be used in the useEffect
hook, event handler, etc.
const getCount = useLocationGetState({
name: "count",
defaultValue: 0,
storeName: "session",
});
useEffect(() => {
const count = getCount();
// ...
}, [getCount]);
type SetState<T> = (valueOrUpdater: T | ((prev: T) => T)) => void;
declare const useLocationSetState: <T>(
definition: LocationStateDefinition<T, DefaultStoreName>,
) => SetState<T>;
Allows updating of the state associated with the current history location from a specified Store
.
T
: Type of state.
definition
: SeeLocationStateDefinition
.
Returns the update function of state.
const setCount = useLocationSetState({
name: "count",
defaultValue: 0,
storeName: "session",
});
declare const useLocationKey: ({ serverDefault, clientDefault, }?: {
serverDefault?: string | undefined;
clientDefault?: string | undefined;
} | undefined) => string | undefined;
Returns the key associated with the current history location from the Syncer
. This hook subscribes to re-render the component if there is a change in the key.
serverDefault
: Key on the server. This key is used when server side and client hydration. If not specified,undefined
is used.clientDefault
: Default key when key is not available. If not specified,undefined
is used.
Returns the key associated with the current history location.
const locationKey = useLocationKey();
declare function LocationStateProvider({
children,
...props
}: {
syncer?: Syncer;
stores?: Stores | ((syncer: Syncer) => Stores);
children: ReactNode;
}): JSX.Element;
Context Provider of location-state
.
syncer?
: Specifies howlocation-state
synchronizes with history. It must implementSyncer
. If not specified,NavigationSyncer
instance is used.stores?
:Stores
that persist state. If not specified,createDefaultStores()
is used.
export function Providers({ children }: { children: React.ReactNode }) {
return (
<LocationStateProvider syncer={syncer} stores={stores}>
{children}
</LocationStateProvider>
);
}
export declare const createDefaultStores: (syncer: Syncer) => Stores;
Create default Stores
to be used by <LocationStateProvider>
.
syncer?
: Specifies howlocation-state
synchronizes with history. It must implementSyncer
. If not specified,NavigationSyncer
instance is used.
Returns Stores
with the following properties.
Store Name | Store | detail |
---|---|---|
"session" |
StorageStore |
Store to persist in session storage. |
"url" |
URLStore |
Store to persist in a URL query string. |
const defaultStores = createDefaultStores(syncer);
export declare const getHooksWith: <StoreName extends string>() => {
useLocationState: <T>(
definition: LocationStateDefinition<T, StoreName>,
) => [T, SetState<T>];
useLocationStateValue: <T>(
definition: LocationStateDefinition<T, StoreName>,
) => T;
useLocationSetState: <T>(
definition: LocationStateDefinition<T, StoreName>,
) => SetState<T>;
};
Returns state hooks that allows a type parameter to be specified for the storeName of the LocationStateDefinition
. This is useful when you specify custom stores for the <LocationStateProvider>
.
StoreName
: The type of theStore
name.
Returns the following hooks to which StoreName
is bound.
export const { useLocationState, useLocationStateValue, useLocationSetState } =
getHooksWith<"local" | "indexeddb">();
type Syncer = {
key(): string | undefined;
sync(arg: { listener: (key: string) => void; signal: AbortSignal }): void;
updateURL(url: string): void;
};
Syncer
is an interface for synchronizing with history location. You can implement a Syncer
to customize how to synchronize with the history location.
key()
: Returns a stable identifier string for the current history location. On the server side, returnsundefined
.sync({ listener, signal })
: Called to synchronize with the history location. Call back thelistener
function when the history location is changed. When signal has been aborted, do not call back thelistener
anymore.updateURL(url)
: Update the browser's URL. It is used to persist state by URL.
export declare class NavigationSyncer implements Syncer {
constructor(navigation?: Navigation | undefined);
}
Syncer
implementation that uses the Navigation API to synchronize with history location.
navigation?
:window.navigation
or implementation of Navigation API. Passundefined
when server side.
const navigationSyncer = new NavigationSyncer(
typeof window !== "undefined" ? window.navigation : undefined,
);
Provides a temporary implementation for browsers that do not support the Navigation API. The actual value is below, depending on the runtime environment.
- Server side
undefined
- Client side
window.navigation
when the Navigation API is supported.- Otherwise, Navigation API polyfill (partially implemented).
Warning This is a polyfill-like implementation that partially supports the behavior of the Navigation API, but the scope of implementation is minimal and the
location-state
does not actively test and support it.
import { unsafeNavigation } from "@location-state/core/unsafe-navigation";
const navigationSyncer = new NavigationSyncer(unsafeNavigation);
type Unsubscribe = () => void;
type Store = {
subscribe(name: string, listener: Listener): Unsubscribe;
get(name: string): unknown;
set(name: string, value: unknown): void;
load(key: string): void;
save(): void;
};
Store
is an interface to implement state retention and persistence.
subscribe(name, listener)
: Calllistener
whenstate[name]
changes. Return a function tounsubscribe
.get(name)
: Returnsstate[name]
.set(name, value)
: Updatestate[name]
withvalue
.load(key)
: Load state from destination usingkey
in history location and update state.save()
: Save state to destination with currentkey
.
export type Stores = Record<string, Store>;
Stores
is a key-value object of Store
.
type StateSerializer = {
serialize: (value: Record<string, unknown>) => string;
deserialize: (value: string) => Record<string, unknown>;
};
Interface to serialize/deserialize state. It may be used for Store
s customization.
export declare class StorageStore implements Store {
constructor(storage?: Storage | undefined, stateSerializer?: StateSerializer);
}
A Store
that stores state in Storage
.
storage?
: TheStorage
of the destination. On the client side, passglobalThis.sessionStorage
orglobalThis.localStorage
. On the server side, passundefined
.stateSerializer?
: Specifies how to serialize/deserialize. By default,JSON.stringify
andJSON.parse
are used.
const sessionStore = new StorageStore(
typeof window !== "undefined" ? globalThis.sessionStorage : undefined,
);
type URLEncoder = {
encode: (url: string, state?: Record<string, unknown>) => string;
decode: (url: string) => Record<string, unknown>;
};
Interface to URL encoding/decoding. It may be used for URLStore
s customization.
export declare class URLStore implements Store {
constructor(syncer: Syncer, urlEncoder?: URLEncoder);
}
A Store
that stores state in a URL.
syncer
: Implementation ofSyncer
used for URL updates.urlEncoder?
: Implementation ofURLEncoder
used for URL encoding/decoding. By default,defaultSearchParamEncoder
is used.
const urlStore = new URLStore(syncer);
const customUrlStore = new URLStore(syncer, {
encode: encodeUrlState,
decode: decodeUrlState,
});
declare function searchParamEncoder(
paramName: string,
stateSerializer: StateSerializer,
): URLEncoder;
Generate a URLEncoder
with the query parameter name and StateSerializer
.
declare const defaultSearchParamEncoder: URLEncoder;
This is the URLEncoder
that URLStore
uses by default. Serialize/Deserialize the state in the location-state
query parameter with JSON.stringify
/JSON.parse
.
// Example of saving `counter: 1`.
https://test.com?location-state=%7B%22counter%22%3A1%7D