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, react-router@6-7, and remix@2.

2 lines (1 loc) 1.36 kB
import f from"react";import{TIMEOUT as k}from"../constants/constants.mjs";import{useInsertionEffect as C}from"../useInsertionEffect.mjs";import{useSharedState as P}from"../useSharedState/useSharedState.mjs";import{useUrlEncode as b}from"../useUrlEncode/useUrlEncode.mjs";import{popstateEv as h,getOtherParams as y,filterUnknownParamsClient as I,getSearch as L}from"../utils.mjs";let a;let o;function O(t,r,w,g){const{parse:c,stringify:l}=b(t);const{state:v,getState:s,setState:n}=P(t,()=>w?.({parse:c})||t);C(()=>{const e=()=>{n(c(I(t,L())))};window.addEventListener(h,e);return()=>{window.removeEventListener(h,e)}},[]);const i=f.useCallback((e,U)=>{const u=typeof e==="function"?e(s(),t):{...s(),...e};const p=l(u,y(t,window.location.search));const d=x(window.location.pathname,g);const m=`${d}${p.length?"?":""}${p}${window.location.hash}`;const $=`${d}${window.location.search}${window.location.hash}`;if(m===$)return;n(u);const{replace:E,...T}=U||{};clearTimeout(a);a=void 0;o={router:r,method:E?"replace":"push",url:m,opts:T};a=setTimeout(()=>{if(o){o.router[o.method](o.url,o.opts);o=void 0}a=void 0},k)},[r,l,s]);const S=f.useCallback(e=>{n(t);i(t,e)},[i,n]);return{updateState:n,updateUrl:i,state:v,reset:S,getState:s,pendingUrlUpdate:()=>a!==void 0}}function x(t,r){if(!r||r==="/"){return t}return t.slice(r.length)}export{O as useUrlStateBase};