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) • 2.48 kB
JavaScript
;var R=require("react");var A=require("../constants/constants.cjs");var S=require("../subscribers.cjs");var D=require("../useIsomorphicLayoutEffect.cjs");var F=require("../useSharedState/useSharedState.cjs");var H=require("../useUrlEncode/useUrlEncode.cjs");var o=require("../utils.cjs");function J(t){return t&&t.__esModule?t:{default:t}}var i=J(R);let g;let a;let s;let E;let U=0;const b=()=>window.location.pathname+window.location.search;function f(){s=void 0;E?.();E=void 0}function d(){if(!s)return void 0;const t=b();if(t===s.from&&t!==s.to){return s}f();return void 0}function K(t,e){const n=d()?.from??b();if(n===t){f();return}s={from:n,to:t,search:e};E??=o.subscribeToUrl(f)}function N(t){if(t.pathname!==window.location.pathname)return;const e=d();const n=t.pathname+t.search;if(e?.to===n)return;const u=n===b();if(u&&!e)return;const h=u?"replace":t.method;t.router[h](t.url,t.opts);K(n,t.search)}function y(){return!!a&&a.pathname===window.location.pathname}function W(t,e,n,u,h=true){const{parse:p,stringify:q}=H.useUrlEncode(t);i.default.useState(()=>{if(o.isSSR||!n||!h)return;const r=!S.subscribers.get(t).length;if(!r||y()||d())return;const l=n({parse:p});if(!o.isEqual(S.stateMap.get(t),l))S.stateMap.set(t,l)});const{state:C,getState:c,setState:w}=F.useSharedState(t,()=>n?.({parse:p})||t);const m=i.default.useRef();if(m.current===void 0)m.current=o.getSearch();D.useIsomorphicLayoutEffect(()=>{const r=()=>{w(p(o.filterUnknownParamsClient(t,o.getSearch())))};window.addEventListener(o.popstateEv,r);if(m.current!==o.getSearch())r();return()=>{window.removeEventListener(o.popstateEv,r)}},[]);i.default.useEffect(()=>{U+=1;return()=>{U-=1;if(U===0)f()}},[]);const v=i.default.useCallback((r,l)=>{const $=typeof r==="function"?r(c(),t):{...c(),...r};w($);const T=a?.search??d()?.search??window.location.search;const L=q($,o.getOtherParams(t,T));const M=L.length?`?${L}`:"";const _=j(window.location.pathname,u);const k=`${_}${M}${window.location.hash}`;if(k===`${_}${T}${window.location.hash}`)return;const{replace:B,...O}=l||{};clearTimeout(g);a={router:e,method:B?"replace":"push",url:k,pathname:window.location.pathname,search:M,opts:O};g=setTimeout(()=>{g=void 0;if(!a)return;const P=a;a=void 0;N(P)},A.TIMEOUT)},[e,q,c]);const I=i.default.useCallback(r=>v(t,r),[v]);return{updateState:w,updateUrl:v,state:C,reset:I,getState:c,pendingUrlUpdate:y}}function j(t,e){if(!e||e==="/"){return t}return t.slice(e.length)}exports.useUrlStateBase=W;