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.28 kB
JavaScript
import r from"react";import{useRouter as y}from"next/navigation";import{parseSPObj as p}from"../../parseSPObj.mjs";import{useUrlStateBase as C}from"../../useUrlStateBase/useUrlStateBase.mjs";import{routerHistory as m,filterUnknownParams as f,getParams as v,subscribeToUrl as H,isSSR as M,filterUnknownParamsClient as j,getSearch as S}from"../../utils.mjs";function w(s,t){const c=r.useMemo(()=>t?.useHistory===void 0?true:!!t?.useHistory,[]);const a=y();const U=r.useMemo(()=>({push:(...e)=>{if(c){m.push(...e)}else{a.push(...e)}},replace:(...e)=>{if(c){m.replace(...e)}else{a.replace(...e)}}}),[a]);const{state:b,updateState:u,updateUrl:n,reset:i,getState:d,pendingUrlUpdate:h}=C(s,U,({parse:e})=>{return M?p(f(s,t?.searchParams),s):e(j(s,t?.searchParams||S()))});const l=r.useCallback(()=>{if(h())return;u(f(s,p(Object.fromEntries(v(S()).entries()),s)))},[]);r.useEffect(()=>{l();return H(l)},[l]);const o=r.useMemo(()=>{const e={...E};if(t?.scroll!==void 0)e.scroll=t.scroll;if(t?.replace!==void 0)e.replace=t.replace;return e},[t?.scroll,t?.replace]);const P=r.useCallback((e,k)=>n(e,{...o,...k}),[n,o]);const g=r.useCallback(e=>{i({...o,...e})},[i,o]);return{setState:u,setUrl:P,urlState:b,reset:g,getState:d}}const E={replace:true,scroll:false};export{w as useUrlState};