UNPKG

state-in-url

Version:

Store state in URL as in object, types and structure are preserved, with TS validation. Same API as React.useState, wthout any hasssle or boilerplate. Next.js@14-15 and react-router@6-7.

2 lines (1 loc) 1.58 kB
import u from"react";import{TIMEOUT as y}from"../constants/constants.mjs";import{useInsertionEffect as L}from"../useInsertionEffect.mjs";import{useSharedState as T}from"../useSharedState/useSharedState.mjs";import{useUrlEncode as v}from"../useUrlEncode/useUrlEncode.mjs";import{filterUnknownParamsClient as R}from"../utils.mjs";function b(t,c,f){const{parse:s,stringify:r}=v(t);const{state:a,getState:n,setState:o}=T(t,()=>f?.({parse:s})||t);const l=u.useRef(void 0);L(()=>{const e=()=>{const m=s(R(t,P()));o(m)};window.addEventListener($,e);return()=>{window.removeEventListener($,e);clearTimeout(l.current)}},[o]);const i=u.useRef([]);const w=u.useCallback((e,m)=>{const d=typeof e==="function"?e(n()):{...n(),...e};const h=r(d,C(t));const S=`${window.location.pathname}${h.length?"?":""}${h}${window.location.hash}`;const g=`${window.location.pathname}${window.location.search}${window.location.hash}`;if(S===g)return;o(d);const{replace:k,...E}=m||{};i.current.push([k?"replace":"push",S,E]);clearTimeout(l.current);queueMicrotask(()=>{if(!i.current.length)return;l.current=setTimeout(()=>{const p=i.current.at(-1);i.current=[];c[p[0]](p[1],p[2])},y)})},[c,r,n]);const U=u.useCallback(e=>{o(t);w(t,e)},[w,o]);return{updateState:o,updateUrl:w,state:a,reset:U,getState:n}}function C(t){const c=Object.keys(t);const f=window.location.search;const s=new URLSearchParams(f);const r=new URLSearchParams;for(const[a,n]of s){!c.includes(a)&&r.set(a,n)}return r}const $="popstate";function P(){return typeof window!=="undefined"&&window.location.search||""}export{b as useUrlStateBase};