Skip to content

Commit

Permalink
(BSR) refactor(Zustand): rewrite createStore (#7501)
Browse files Browse the repository at this point in the history
* feat: add modal logic + a start of architecture

* feat: remove created modal manager + rename createStore => createConfiguredStore

* feat: replace createConfiguredStore by createStore

* refactor: take reviews
  • Loading branch information
xlecunff-pass authored Jan 14, 2025
1 parent 0a3218e commit 614e12a
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 97 deletions.
10 changes: 5 additions & 5 deletions src/features/identityCheck/api/useCreditStore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

type CreditState = {
Expand All @@ -9,12 +8,13 @@ const defaultState: CreditState = {
activationDate: undefined,
}

const useCreditStore = createStore({
const creditStore = createStore({
name: 'credit',
defaultState,
options: { persist: true },
actions: (set) => ({
setActivationDate: (activationDate: Date) => set({ activationDate }),
}),
})

export const creditActions = createActions(useCreditStore, (set) => ({
setActivationDate: (activationDate: Date) => set({ activationDate }),
}))
export const creditActions = creditStore.actions
14 changes: 7 additions & 7 deletions src/features/identityCheck/pages/profile/store/addressStore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

type State = {
Expand All @@ -7,15 +6,16 @@ type State = {

const defaultState: State = { address: null }

const useAddressStore = createStore({
const addressStore = createStore({
name: 'profile-address',
defaultState,
actions: (set) => ({
setAddress: (address: string) => set({ address }),
resetAddress: () => set(defaultState),
}),
options: { persist: true },
})

export const addressActions = createActions(useAddressStore, (set) => ({
setAddress: (address: string) => set({ address }),
resetAddress: () => set(defaultState),
}))
export const addressActions = addressStore.actions

export const useAddress = () => useAddressStore((state) => state.address)
export const useAddress = () => addressStore.useStore((state) => state.address)
15 changes: 8 additions & 7 deletions src/features/identityCheck/pages/profile/store/cityStore.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { SuggestedCity } from 'libs/place/types'
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

type State = { city: SuggestedCity | null }

const defaultState: State = { city: null }

const useCityStore = createStore({
const cityStore = createStore({
name: 'profile-city',
defaultState,
actions: (set) => ({
setCity: (city: SuggestedCity) => set({ city }),
resetCity: () => set(defaultState),
}),
options: {
persist: true,
},
})

export const useCity = () => useCityStore((state) => state.city)
const useCityStore = cityStore.useStore
export const cityActions = cityStore.actions

export const cityActions = createActions(useCityStore, (set) => ({
setCity: (city: SuggestedCity) => set({ city }),
resetCity: () => set(defaultState),
}))
export const useCity = () => useCityStore((state) => state.city)
19 changes: 11 additions & 8 deletions src/features/identityCheck/pages/profile/store/nameStore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

interface Name {
Expand All @@ -10,11 +9,15 @@ type State = { name: Name | null }

const defaultState: State = { name: null }

const useNameStore = createStore({ name: 'profile-name', defaultState, options: { persist: true } })
const nameStore = createStore({
name: 'profile-name',
defaultState,
actions: (set) => ({
setName: (name: Name) => set({ name }),
resetName: () => set(defaultState),
}),
options: { persist: true },
})

export const useName = () => useNameStore((state) => state.name)

export const nameActions = createActions(useNameStore, (set) => ({
setName: (name: Name) => set({ name }),
resetName: () => set(defaultState),
}))
export const nameActions = nameStore.actions
export const useName = () => nameStore.useStore((state) => state.name)
13 changes: 7 additions & 6 deletions src/features/venueMap/store/initialVenuesStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Venue } from 'features/venue/types'
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

type State = {
Expand All @@ -8,14 +7,16 @@ type State = {

const defaultState: State = { initialVenues: [] }

const useInitialVenuesStore = createStore({
const initialVenuesStore = createStore({
name: 'venue-map-store',
defaultState,
actions: (set) => ({
setInitialVenues: (initialVenues: Venue[]) => set({ initialVenues }),
}),
options: { persist: true },
})

export const useInitialVenues = () => useInitialVenuesStore((state) => state.initialVenues)
const useInitialVenuesStore = initialVenuesStore.useStore
export const initialVenuesActions = initialVenuesStore.actions

export const initialVenuesActions = createActions(useInitialVenuesStore, (set) => ({
setInitialVenues: (initialVenues: Venue[]) => set({ initialVenues }),
}))
export const useInitialVenues = () => useInitialVenuesStore((state) => state.initialVenues)
17 changes: 10 additions & 7 deletions src/features/venueMap/store/selectedVenueStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { GeolocatedVenue } from 'features/venueMap/components/VenueMapView/types'
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

type State = {
Expand All @@ -8,11 +7,15 @@ type State = {

const defaultState: State = { selectedVenue: null }

const useSelectedVenueStore = createStore({ name: 'venue-map-selected-venue', defaultState })
const selectedVenueStore = createStore({
name: 'venue-map-selected-venue',
defaultState,
actions: (set) => ({
setSelectedVenue: (selectedVenue: GeolocatedVenue) => set({ selectedVenue }),
removeSelectedVenue: () => set(defaultState),
}),
})

export const useSelectedVenue = () => useSelectedVenueStore((state) => state.selectedVenue)
export const selectedVenueActions = selectedVenueStore.actions

export const selectedVenueActions = createActions(useSelectedVenueStore, (set) => ({
setSelectedVenue: (selectedVenue: GeolocatedVenue) => set({ selectedVenue }),
removeSelectedVenue: () => set(defaultState),
}))
export const useSelectedVenue = () => selectedVenueStore.useStore((state) => state.selectedVenue)
15 changes: 9 additions & 6 deletions src/features/venueMap/store/venueTypeCodeStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { VenueTypeCode } from 'libs/parsers/venueType'
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

type State = {
Expand All @@ -8,9 +7,13 @@ type State = {

const defaultState: State = { venueTypeCode: null }

const useVenueTypeCodeStore = createStore({ name: 'venue-map-venue-type-code', defaultState })
const venueTypeCodeStore = createStore({
name: 'venue-map-venue-type-code',
defaultState,
actions: (set) => ({
setVenueTypeCode: (venueTypeCode: VenueTypeCode | null) => set({ venueTypeCode }),
}),
})

export const useVenueTypeCode = () => useVenueTypeCodeStore((state) => state.venueTypeCode)
export const venueTypeCodeActions = createActions(useVenueTypeCodeStore, (set) => ({
setVenueTypeCode: (venueTypeCode: VenueTypeCode | null) => set({ venueTypeCode }),
}))
export const venueTypeCodeActions = venueTypeCodeStore.actions
export const useVenueTypeCode = () => venueTypeCodeStore.useStore((state) => state.venueTypeCode)
33 changes: 18 additions & 15 deletions src/features/venueMap/store/venuesFilterStore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { difference } from 'lodash'

import { VenueTypeCodeKey } from 'api/gen'
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

type State = {
Expand All @@ -12,19 +11,23 @@ const defaultState: State = {
venuesFilters: [],
}

const useVenuesFilterStore = createStore({ name: 'venue-filter', defaultState })
const venuesFilterStore = createStore({
name: 'venue-filter',
defaultState,
actions: (set) => ({
setVenuesFilters: (venuesFilters: VenueTypeCodeKey[]) => set((_) => ({ venuesFilters })),
addVenuesFilters: (venueTypeCodeKeys: VenueTypeCodeKey[]) =>
set((state: State) => ({
venuesFilters: Array.from(new Set([...state.venuesFilters, ...venueTypeCodeKeys])),
})),
removeVenuesFilters: (venueTypeCodeKeys: VenueTypeCodeKey[]) =>
set((state: State) => ({
venuesFilters: difference(state.venuesFilters, venueTypeCodeKeys),
})),
reset: () => set((_) => ({ venuesFilters: [] })),
}),
})

export const useVenuesFilter = () => useVenuesFilterStore((state) => state.venuesFilters)
export const venuesFilterActions = venuesFilterStore.actions

export const venuesFilterActions = createActions(useVenuesFilterStore, (set) => ({
setVenuesFilters: (venuesFilters: VenueTypeCodeKey[]) => set((_) => ({ venuesFilters })),
addVenuesFilters: (venueTypeCodeKeys: VenueTypeCodeKey[]) =>
set((state: State) => ({
venuesFilters: Array.from(new Set([...state.venuesFilters, ...venueTypeCodeKeys])),
})),
removeVenuesFilters: (venueTypeCodeKeys: VenueTypeCodeKey[]) =>
set((state: State) => ({
venuesFilters: difference(state.venuesFilters, venueTypeCodeKeys),
})),
reset: () => set((_) => ({ venuesFilters: [] })),
}))
export const useVenuesFilter = () => venuesFilterStore.useStore((state) => state.venuesFilters)
16 changes: 9 additions & 7 deletions src/features/venueMap/store/venuesStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Venue } from 'features/venue/types'
import { createActions } from 'libs/store/createActions'
import { createStore } from 'libs/store/createStore'

type State = {
Expand All @@ -8,10 +7,13 @@ type State = {

const defaultState: State = { venues: [] }

const useVenuesStore = createStore({ name: 'venue-map-venues', defaultState })
const venuesStore = createStore({
name: 'venue-map-venues',
defaultState,
actions: (set) => ({
setVenues: (venues: Venue[]) => set({ venues }),
}),
})

export const useVenues = () => useVenuesStore((state) => state.venues)

export const venuesActions = createActions(useVenuesStore, (set) => ({
setVenues: (venues: Venue[]) => set({ venues }),
}))
export const venuesActions = venuesStore.actions
export const useVenues = () => venuesStore.useStore((state) => state.venues)
16 changes: 0 additions & 16 deletions src/libs/store/createActions.ts

This file was deleted.

47 changes: 34 additions & 13 deletions src/libs/store/createStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,45 @@ import AsyncStorage from '@react-native-async-storage/async-storage'
import { create } from 'zustand'
import { createJSONStorage, devtools, persist } from 'zustand/middleware'

type Options = {
persist?: boolean
}
import { AnyFunction, CurriedAnyFunction, StoreConfig, Store } from './store.types'

type Params<State> = {
name: string
defaultState: State
options?: Options
}
export function createStore<
State,
Actions extends Record<string, AnyFunction>,
Selectors extends Record<string, CurriedAnyFunction<State>>,
>({
name,
defaultState,
actions: createActions = createEmptyActions<Actions>,
selectors = createEmptySelectors<Selectors>(),
options,
}: StoreConfig<State, Actions, Selectors>): Store<State, Actions, Selectors> {
const defaultStore = () => defaultState

export const createStore = <State>({ name, defaultState, options }: Params<State>) => {
const store = () => defaultState
const persistedStore = persist(store, {
const persistedStore = persist(defaultStore, {
name,
storage: createJSONStorage(() => AsyncStorage),
})

return create<State>()(
devtools(options?.persist ? persistedStore : store, { enabled: false, name })
const store = create<State>()(
devtools(options?.persist ? persistedStore : defaultStore, { enabled: false, name })
)

const actions = createActions(store.setState)

const select = <T>(selector: (state: State) => T): T => {
const state = store.getState()
return selector(state)
}

return {
useStore: store,
actions,
selectors,
select,
}
}

const createEmptyActions = <T extends Record<string, AnyFunction>>(): T => Object.create(null)
const createEmptySelectors = <T extends Record<string, CurriedAnyFunction<never>>>(): T =>
Object.create(null)
29 changes: 29 additions & 0 deletions src/libs/store/store.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { StoreApi, UseBoundStore } from 'zustand'

export type AnyFunction = (...args: never) => unknown
export type CurriedAnyFunction<State> = (...args: never) => (state: State) => unknown
type Options = {
persist?: boolean
}
type StoreType<State> = UseBoundStore<StoreApi<State>>
export type StoreConfig<
State,
Actions extends Record<string, AnyFunction>,
Selectors extends Record<string, CurriedAnyFunction<State>>,
> = {
name: string
defaultState: State
actions?: (setState: StoreType<State>['setState']) => Actions
selectors?: Selectors
options?: Options
}
export type Store<
State,
Actions extends Record<string, AnyFunction>,
Selectors extends Record<string, CurriedAnyFunction<State>>,
> = {
useStore: UseBoundStore<StoreApi<State>>
actions: Actions
selectors: Selectors
select: <T>(selector: (state: State) => T) => T
}

0 comments on commit 614e12a

Please sign in to comment.