Переглянути джерело

Move active user state to zustand (#1184)

* move active user state to zustand

* fix naming
Bartosz Dryl 3 роки тому
батько
коміт
64504ccd1a
2 змінених файлів з 44 додано та 30 видалено
  1. 38 27
      src/providers/user/store.ts
  2. 6 3
      src/providers/user/user.tsx

+ 38 - 27
src/providers/user/store.ts

@@ -1,6 +1,6 @@
-import { useCallback, useEffect, useState } from 'react'
-
 import { AccountId, ChannelId, MemberId } from '@/joystream-lib'
+import { createStore } from '@/store'
+import { readFromLocalStorage } from '@/utils/localStorage'
 
 const LOCAL_STORAGE_KEY = 'activeUser'
 
@@ -16,30 +16,41 @@ const EMPTY_STATE: ActiveUserState = {
   channelId: null,
 }
 
-const getInitialState = (): ActiveUserState => {
-  const rawData = localStorage.getItem(LOCAL_STORAGE_KEY)
-  return rawData ? JSON.parse(rawData) : EMPTY_STATE
-}
-
-export const useActiveUserStore = () => {
-  const [state, setState] = useState<ActiveUserState>(getInitialState())
-
-  // synchronize state with local storage on change
-  useEffect(() => {
-    const rawData = JSON.stringify(state)
-    localStorage.setItem(LOCAL_STORAGE_KEY, rawData)
-  }, [state])
+const WHITELIST = ['accountId', 'memberId', 'channelId'] as (keyof ActiveUserState)[]
 
-  const setActiveUser = useCallback((changes: Partial<ActiveUserState>) => {
-    setState((currentState) => ({
-      ...currentState,
-      ...changes,
-    }))
-  }, [])
-
-  const resetActiveUser = useCallback(() => {
-    setState(EMPTY_STATE)
-  }, [])
-
-  return { activeUserState: state, setActiveUser, resetActiveUser }
+export type ActiveUserStoreActions = {
+  resetActiveUser: () => void
+  setActiveUser: (activeUserChanges: Partial<ActiveUserState>) => void
 }
+
+export const useActiveUserStore = createStore<ActiveUserState, ActiveUserStoreActions>(
+  {
+    state: EMPTY_STATE,
+    actionsFactory: (set) => ({
+      resetActiveUser: () => {
+        set((state) => ({ ...state, ...EMPTY_STATE }))
+      },
+      setActiveUser: (activeUserChanges) => {
+        set((state) => {
+          state.accountId = activeUserChanges.accountId || state.accountId
+          state.memberId = activeUserChanges.memberId || state.memberId
+          state.channelId = activeUserChanges.channelId || state.channelId
+        })
+      },
+    }),
+  },
+  {
+    persist: {
+      key: LOCAL_STORAGE_KEY,
+      version: 0,
+      whitelist: WHITELIST,
+      migrate: (oldState, oldVersion) => {
+        // migrate store before zustand was added
+        if (oldVersion === undefined) {
+          const activeUser = readFromLocalStorage<ActiveUserState>(LOCAL_STORAGE_KEY)
+          return activeUser
+        }
+      },
+    },
+  }
+)

+ 6 - 3
src/providers/user/user.tsx

@@ -7,14 +7,15 @@ import { WEB3_APP_NAME } from '@/config/urls'
 import { AccountId } from '@/joystream-lib'
 import { Logger } from '@/utils/logger'
 
-import { useActiveUserStore } from './store'
+import { ActiveUserState, ActiveUserStoreActions, useActiveUserStore } from './store'
 
 export type Account = {
   id: AccountId
   name: string
 }
 
-type ActiveUserContextValue = ReturnType<typeof useActiveUserStore> & {
+type ActiveUserContextValue = ActiveUserStoreActions & {
+  activeUserState: ActiveUserState
   accounts: Account[] | null
   extensionConnected: boolean | null
 
@@ -28,11 +29,13 @@ type ActiveUserContextValue = ReturnType<typeof useActiveUserStore> & {
 
   userInitialized: boolean
 }
+
 const ActiveUserContext = React.createContext<undefined | ActiveUserContextValue>(undefined)
 ActiveUserContext.displayName = 'ActiveUserContext'
 
 export const ActiveUserProvider: React.FC = ({ children }) => {
-  const { activeUserState, setActiveUser, resetActiveUser } = useActiveUserStore()
+  const activeUserState = useActiveUserStore(({ actions, ...activeUser }) => ({ ...activeUser }))
+  const { setActiveUser, resetActiveUser } = useActiveUserStore((state) => state.actions)
 
   const [accounts, setAccounts] = useState<Account[] | null>(null)
   const [extensionConnected, setExtensionConnected] = useState<boolean | null>(null)