-
-
Save cef62/f00b0d0f0827d96d1a01154110b3e7a0 to your computer and use it in GitHub Desktop.
Revisions
-
tannerlinsley revised this gist
May 15, 2023 . 1 changed file with 7 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,7 @@ This middleware does a few interesting things: - Ensures a `url` shape in the zustand store, where we'll store URL information. - Assumes we will be storing our `url` state slice in the `?state` search parameter after it has been stringified and base 64 encoded. - On creation, decodes stores state from the `?state` search parameter into the `url` slice of our store. - After each state update, updates the `?state` search parameter with the new `url` state slice. - Sets up an event listener that listens for `popstate` and re-decodes the state from the URL into our store. -
tannerlinsley revised this gist
May 15, 2023 . No changes.There are no files selected for viewing
-
tannerlinsley revised this gist
May 15, 2023 . No changes.There are no files selected for viewing
-
tannerlinsley revised this gist
May 15, 2023 . No changes.There are no files selected for viewing
-
tannerlinsley revised this gist
May 15, 2023 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,7 @@ import { create, type StateCreator } from 'zustand' import { immer } from 'zustand/middleware/immer' function functionalUpdate (updater, previous) { return typeof updater === 'function' ? updater(previous) : updater } -
tannerlinsley revised this gist
May 15, 2023 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -18,7 +18,7 @@ export type PageContext = { projectId?: string } export type Page = 'projects' | 'projects.project' const urlMiddleware = <TState extends { url: any }>( -
tannerlinsley created this gist
May 15, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,91 @@ import { create, type StateCreator } from 'zustand' import { immer } from 'zustand/middleware/immer' funciton functionalUpdate (updater, previous) { return typeof updater === 'function' ? updater(previous) : updater } export type Store = { url: { page: Page context: PageContext } setPage: (page: Page, context?: PageContext) => void createProject: () => void } export type PageContext = { projectId?: string } export type Page = 'projects' | 'projects.project' | 'plants' | 'products' const urlMiddleware = <TState extends { url: any }>( prev: StateCreator<TState, any, any> ): StateCreator<TState> => (set, get, api) => { const parseUrlState = () => { try { const search = new URLSearchParams(window.location.search.substring(1)).get( 'state' ) || '' const decoded = atob(search) return JSON.parse(decoded) } catch (e) { return } } const initialState = prev( (...args) => { set(...args) const stringified = JSON.stringify(get().url) const encoded = btoa(stringified) history.pushState(null, '', `/?state=${encoded}`) }, get, api ) window.addEventListener('popstate', () => { set((state) => { return { ...state, url: parseUrlState(), } }) }) return { ...initialState, url: parseUrlState() || initialState.url, } } export const useStore = create( urlMiddleware( immer<Store>((set) => { return { url: { page: 'projects', context: {}, }, setPage: (page, context) => set((draft) => { draft.url.page = page if (context) { draft.url.context = functionalUpdate(context, draft.url.context) } }), createProject: () => { set((draft) => { draft.url.page = 'projects.project' draft.url.context.projectId = undefined }) }, } }) ) )