From 6222bb58f36bce3c0db9d321d4900c35d0c28dde Mon Sep 17 00:00:00 2001 From: Jing Hua Date: Sun, 5 Mar 2023 23:56:26 +0800 Subject: [PATCH] improve caching --- src/App.tsx | 27 +++---------------- src/components/ConfigMenu/ConfigMenu.tsx | 7 ++--- .../Menu/MenuOptions/ThemeSwitcher.tsx | 23 +++++----------- src/store/config-slice.ts | 10 +++++++ src/store/store.ts | 26 +++++++++++++----- src/types/theme.ts | 1 + 6 files changed, 42 insertions(+), 52 deletions(-) create mode 100644 src/types/theme.ts diff --git a/src/App.tsx b/src/App.tsx index 6ae955b..d393cc3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,39 +1,18 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useRef } from 'react'; import useStore from '@store/store'; import Chat from './components/Chat'; import Menu from './components/Menu'; import ConfigMenu from './components/ConfigMenu'; -import useSaveToLocalStorage from '@hooks/useSaveToLocalStorage'; import useInitialiseNewChat from '@hooks/useInitialiseNewChat'; -import { ChatInterface } from '@type/chat'; - function App() { - useSaveToLocalStorage(); const initialiseNewChat = useInitialiseNewChat(); - const setChats = useStore((state) => state.setChats); - const setCurrentChatIndex = useStore((state) => state.setCurrentChatIndex); - useEffect(() => { - const storedChats = localStorage.getItem('chats'); - if (storedChats) { - try { - const chats: ChatInterface[] = JSON.parse(storedChats); - if (chats.length > 0) { - setChats(chats); - setCurrentChatIndex(0); - } else { - initialiseNewChat(); - } - } catch (e: unknown) { - setChats([]); - setCurrentChatIndex(-1); - console.log(e); - } - } else { + const chats = useStore.getState().chats; + if (!chats || chats.length === 0) { initialiseNewChat(); } }, []); diff --git a/src/components/ConfigMenu/ConfigMenu.tsx b/src/components/ConfigMenu/ConfigMenu.tsx index 96346f4..87757e1 100644 --- a/src/components/ConfigMenu/ConfigMenu.tsx +++ b/src/components/ConfigMenu/ConfigMenu.tsx @@ -23,7 +23,6 @@ const ConfigMenu = () => { if (valid) { setApiKey(_apiKey); - localStorage.setItem('apiKey', _apiKey); setError(false); setOpenConfig(false); } else { @@ -40,11 +39,9 @@ const ConfigMenu = () => { }; useEffect(() => { - const storedApiKey = localStorage.getItem('apiKey'); - if (storedApiKey) { + if (apiKey) { setApiFree(false); - setApiKey(storedApiKey); - _setApiKey(storedApiKey); + _setApiKey(apiKey); } }, []); diff --git a/src/components/Menu/MenuOptions/ThemeSwitcher.tsx b/src/components/Menu/MenuOptions/ThemeSwitcher.tsx index edf3995..50f1dd7 100644 --- a/src/components/Menu/MenuOptions/ThemeSwitcher.tsx +++ b/src/components/Menu/MenuOptions/ThemeSwitcher.tsx @@ -1,8 +1,8 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect } from 'react'; +import useStore from '@store/store'; import SunIcon from '@icon/SunIcon'; import MoonIcon from '@icon/MoonIcon'; - -type Theme = 'light' | 'dark'; +import { Theme } from '@type/theme'; const getOppositeTheme = (theme: Theme): Theme => { if (theme === 'dark') { @@ -12,26 +12,15 @@ const getOppositeTheme = (theme: Theme): Theme => { } }; const ThemeSwitcher = () => { - const [theme, setTheme] = useState(); + const theme = useStore((state) => state.theme); + const setTheme = useStore((state) => state.setTheme); const switchTheme = () => { setTheme(getOppositeTheme(theme!)); }; useEffect(() => { - const _theme = localStorage.getItem('theme'); - if (_theme === 'light' || _theme === 'dark') { - setTheme(_theme); - } else { - setTheme('dark'); - } - }, []); - - useEffect(() => { - if (theme) { - document.documentElement.className = theme; - localStorage.setItem('theme', theme); - } + document.documentElement.className = theme; }, [theme]); return theme ? ( diff --git a/src/store/config-slice.ts b/src/store/config-slice.ts index 4103f9e..18b24cc 100644 --- a/src/store/config-slice.ts +++ b/src/store/config-slice.ts @@ -1,16 +1,26 @@ import { StoreSlice } from './store'; +import { Theme } from '@type/theme'; export interface ConfigSlice { openConfig: boolean; + theme: Theme; setOpenConfig: (openConfig: boolean) => void; + setTheme: (theme: Theme) => void; } export const createConfigSlice: StoreSlice = (set, get) => ({ openConfig: false, + theme: 'dark', setOpenConfig: (openConfig: boolean) => { set((prev: ConfigSlice) => ({ ...prev, openConfig: openConfig, })); }, + setTheme: (theme: Theme) => { + set((prev: ConfigSlice) => ({ + ...prev, + theme: theme, + })); + }, }); diff --git a/src/store/store.ts b/src/store/store.ts index b816643..e548e29 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -1,4 +1,5 @@ import create, { SetState, GetState } from 'zustand'; +import { persist } from 'zustand/middleware'; import { ChatSlice, createChatSlice } from './chat-slice'; import { InputSlice, createInputSlice } from './input-slice'; import { AuthSlice, createAuthSlice } from './auth-slice'; @@ -11,11 +12,24 @@ export type StoreSlice = ( get: GetState ) => T; -const useStore = create((set, get) => ({ - ...createChatSlice(set, get), - ...createInputSlice(set, get), - ...createAuthSlice(set, get), - ...createConfigSlice(set, get), -})); +const useStore = create()( + persist( + (set, get) => ({ + ...createChatSlice(set, get), + ...createInputSlice(set, get), + ...createAuthSlice(set, get), + ...createConfigSlice(set, get), + }), + { + name: 'free-chat-gpt', + partialize: (state) => ({ + chats: state.chats, + currentChatIndex: state.currentChatIndex, + apiKey: state.apiKey, + theme: state.theme, + }), + } + ) +); export default useStore; diff --git a/src/types/theme.ts b/src/types/theme.ts new file mode 100644 index 0000000..937ef15 --- /dev/null +++ b/src/types/theme.ts @@ -0,0 +1 @@ +export type Theme = 'light' | 'dark';