Skip to content

Commit

Permalink
fix: history subscription on creation
Browse files Browse the repository at this point in the history
  • Loading branch information
tannerlinsley committed Oct 27, 2023
1 parent d27c666 commit cff5024
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 57 deletions.
4 changes: 2 additions & 2 deletions examples/react/react-search-state/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ function App() {
const projectState = useSearchState({
key: 'project',
useDefaultValue: () => 'Nozzle',
// writeDefault: true,
writeDefault: true,
// defaultReplace: true,
})

const modeState = useSearchState({
key: 'mode',
useDeps: () => [projectState.state],
useDefaultValue: useLocalDefaultValue(() => 'users'),
// writeDefault: true,
writeDefault: true,
usePersister: localPersister,
defaultReplace: true,
})
Expand Down
99 changes: 45 additions & 54 deletions packages/history/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export interface RouterHistory {
createHref: (href: string) => string
block: (blockerFn: BlockerFn) => () => void
flush: () => void
destroy: () => void
update: () => void
}

export interface HistoryLocation extends ParsedPath {
Expand Down Expand Up @@ -50,24 +52,28 @@ const stopBlocking = () => {

function createHistory(opts: {
getLocation: () => HistoryLocation
subscriber: false | ((onUpdate: () => void) => () => void)
pushState: (path: string, state: any, onUpdate: () => void) => void
replaceState: (path: string, state: any, onUpdate: () => void) => void
go: (n: number) => void
back: () => void
forward: () => void
createHref: (path: string) => string
flush?: () => void
destroy?: () => void
}): RouterHistory {
let location = opts.getLocation()
let unsub = () => {}
let subscribers = new Set<() => void>()
let blockers: BlockerFn[] = []
let queue: (() => void)[] = []

const tryFlush = () => {
const onUpdate = () => {
location = opts.getLocation()
subscribers.forEach((subscriber) => subscriber())
}

const tryUnblock = () => {
if (blockers.length) {
blockers[0]?.(tryFlush, () => {
blockers[0]?.(tryUnblock, () => {
blockers = []
stopBlocking()
})
Expand All @@ -78,39 +84,23 @@ function createHistory(opts: {
queue.shift()?.()
}

if (!opts.subscriber) {
onUpdate()
}
onUpdate()
}

const queueTask = (task: () => void) => {
queue.push(task)
tryFlush()
}

const onUpdate = () => {
location = opts.getLocation()
subscribers.forEach((subscriber) => subscriber())
tryUnblock()
}

return {
get location() {
return location
},
subscribe: (cb: () => void) => {
if (subscribers.size === 0) {
unsub =
typeof opts.subscriber === 'function'
? opts.subscriber(onUpdate)
: () => {}
}
subscribers.add(cb)

return () => {
subscribers.delete(cb)
if (subscribers.size === 0) {
unsub()
}
}
},
push: (path: string, state: any) => {
Expand Down Expand Up @@ -159,6 +149,8 @@ function createHistory(opts: {
}
},
flush: () => opts.flush?.(),
destroy: () => opts.destroy?.(),
update: onUpdate,
}
}

Expand Down Expand Up @@ -273,38 +265,8 @@ export function createBrowserHistory(opts?: {
}
}

return createHistory({
const history = createHistory({
getLocation,
subscriber: (onUpdate) => {
window.addEventListener(pushStateEvent, () => {
currentLocation = parseLocation(getHref(), window.history.state)
onUpdate()
})
window.addEventListener(popStateEvent, () => {
currentLocation = parseLocation(getHref(), window.history.state)
onUpdate()
})

var pushState = window.history.pushState
window.history.pushState = function () {
let res = pushState.apply(history, arguments as any)
if (tracking) onUpdate()
return res
}
var replaceState = window.history.replaceState
window.history.replaceState = function () {
let res = replaceState.apply(history, arguments as any)
if (tracking) onUpdate()
return res
}

return () => {
window.history.pushState = pushState
window.history.replaceState = replaceState
window.removeEventListener(pushStateEvent, onUpdate)
window.removeEventListener(popStateEvent, onUpdate)
}
},
pushState: (path, state, onUpdate) =>
queueHistoryAction('push', path, state, onUpdate),
replaceState: (path, state, onUpdate) =>
Expand All @@ -314,7 +276,37 @@ export function createBrowserHistory(opts?: {
go: (n) => window.history.go(n),
createHref: (path) => createHref(path),
flush,
destroy: () => {
window.history.pushState = pushState
window.history.replaceState = replaceState
window.removeEventListener(pushStateEvent, history.update)
window.removeEventListener(popStateEvent, history.update)
},
})

window.addEventListener(pushStateEvent, () => {
currentLocation = parseLocation(getHref(), window.history.state)
history.update
})
window.addEventListener(popStateEvent, () => {
currentLocation = parseLocation(getHref(), window.history.state)
history.update
})

var pushState = window.history.pushState
window.history.pushState = function () {
let res = pushState.apply(window.history, arguments as any)
if (tracking) history.update()
return res
}
var replaceState = window.history.replaceState
window.history.replaceState = function () {
let res = replaceState.apply(window.history, arguments as any)
if (tracking) history.update()
return res
}

return history
}

export function createHashHistory(): RouterHistory {
Expand Down Expand Up @@ -342,7 +334,6 @@ export function createMemoryHistory(

return createHistory({
getLocation,
subscriber: false,
pushState: (path, state) => {
currentState = state
entries.push(path)
Expand Down
2 changes: 1 addition & 1 deletion packages/react-search-state/src/useSearchState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export function useSearchState<
...prev,
[key]: functionalUpdate(updater, prev[key]),
}),
replace: opts?.replace ?? defaultReplace,
replace: opts?.replace ?? defaultReplace ?? true,
state: opts?.state,
})

Expand Down

0 comments on commit cff5024

Please sign in to comment.