11import React , { createContext , Fragment , useCallback , useContext , useEffect , useMemo , useRef , useState } from "react" ;
2+ import { jsonToURLSearchParams } from "../form/form-data-api" ;
23import { RouterNavigator } from "../router/router-navigator" ;
34import type { BroutherFlags , ConfiguredRoute , Location , PathFormat } from "../types" ;
45import { BrowserHistory } from "../types/history" ;
@@ -124,16 +125,16 @@ export const Brouther = <T extends Base>({ config, flags, ErrorElement, children
124125 return void request ( ) . then ( ( response ) =>
125126 setState ( ( prev ) => ( {
126127 ...prev ,
128+ matches : result ,
129+ loading : response . loading ,
127130 error : result . error ?? null ,
128131 loaderData : response . loaderData ,
129- loading : response . loading ,
130- matches : result ,
131132 } ) )
132133 ) ;
133134 } , [ findMatches , state . location . search , state . location . state , config , filter , state . location . pathname ] ) ;
134135
135136 useEffect ( ( ) => {
136- config . history . listen ( ( changes ) => setState ( ( p ) => ( { ...p , location : { ... changes . location } } ) ) ) ;
137+ config . history . listen ( ( changes ) => setState ( ( p ) => ( { ...p , location : changes . location } ) ) ) ;
137138 } , [ config . history ] ) ;
138139
139140 const href = createHref ( state . location . pathname , state . location . search , state . location . hash , config . basename ) ;
@@ -145,21 +146,21 @@ export const Brouther = <T extends Base>({ config, flags, ErrorElement, children
145146 const setLoading = useCallback ( ( loading : boolean ) => setState ( ( prev ) => ( { ...prev , loading } ) ) , [ ] ) ;
146147
147148 const context = {
149+ href,
150+ flags,
151+ config,
148152 setState,
153+ setLoading,
149154 actions : state . actions ,
150155 matches : state . matches ,
151- config,
152- basename : config . basename ,
153- error : state . matches . error ?? state . error ,
154- href,
155- loaderData : state . loaderData ,
156156 loading : state . loading ,
157157 location : state . location ,
158+ basename : config . basename ,
159+ paths : state . matches . params ,
158160 navigation : config . navigation ,
159- flags ,
160- setLoading ,
161+ loaderData : state . loaderData ,
162+ error : state . matches . error ?? state . error ,
161163 page : state . error !== null ? null : state . matches . page ,
162- paths : state . matches . params ,
163164 } ;
164165
165166 return (
@@ -343,3 +344,24 @@ export const useBeforeUnload = (fn: (event: BeforeUnloadEvent) => void) => {
343344export const usePageStats = ( ) => useBrouther ( ) . page ;
344345
345346export const useFormActions = < R extends object > ( ) : ActionState < R > => useBrouther ( ) . actions ;
347+
348+ /*
349+ The query-string state controller.
350+ */
351+ export const useQueryStringState = < T extends { } | string > ( _ ?: T ) : [ qs : T extends string ? QueryString . Parse < T > : T , set : ( newQuery : T ) => void ] => {
352+ const { href, page, navigation, location } = useBrouther ( ) ;
353+ const urlSearchParams = useUrlSearchParams ( ) ;
354+ const qs = useMemo (
355+ ( ) => ( page === null ? ( { } as any ) : transformData ( urlSearchParams , mapUrlToQueryStringRecord ( page . originalPath , fromStringToValue ) ) ) ,
356+ [ href , page , urlSearchParams ]
357+ ) ;
358+ const callback = useCallback (
359+ ( query : T ) => {
360+ const location = new URL ( window . location . href ) ;
361+ location . search = jsonToURLSearchParams ( query ) . toString ( ) ;
362+ navigation . push ( location . href ) ;
363+ } ,
364+ [ navigation ]
365+ ) ;
366+ return [ qs , callback ] ;
367+ } ;
0 commit comments