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-16, react-router@6-7, remix@2, and Astro.
2 lines (1 loc) • 1.21 kB
JavaScript
import a from"react";import{useNavigate as b,useSearchParams as k,useHref as P}from"react-router-dom";import{parseSPObj as C}from"../../parseSPObj.mjs";import{useUrlStateBase as H}from"../../useUrlStateBase/useUrlStateBase.mjs";import{routerHistory as O,filterUnknownParamsClient as h,assignValue as j,filterUnknownParams as w}from"../../utils.mjs";function y(r,t){const f=t?.useHistory;const o=a.useMemo(()=>{const e={...i};if(t?.replace!==void 0)e.replace=t.replace;if(t?.preventScrollReset!==void 0)e.preventScrollReset=t.preventScrollReset;return e},[t?.replace,t?.preventScrollReset]);const l=b();const m=a.useMemo(()=>f?O:{replace:(e,s)=>l(e,{...o,...s,replace:true}),push:(e,s)=>l(e,{...o,...s,replace:false})},[l]);const[n]=k();const S=P("/");const{state:v,updateState:c,updateUrl:p,getState:U,reset:u,pendingUrlUpdate:d}=H(r,m,({parse:e})=>e(h(r,n.entries())),S);const R=a.useCallback((e,s)=>p(e,{...o,...s}),[p]);a.useEffect(()=>{if(!d()){c(j(r,w(r,C(Object.fromEntries([...n.entries()]),r))))}},[n]);const g=a.useCallback(e=>{u({...o,...e})},[u]);return{setState:c,setUrl:R,urlState:v,reset:g,getState:U}}const i={replace:true,preventScrollReset:true};export{i as defaultOpts,y as useUrlState};