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