🐛 fix: 修正水合导致 list 丢失的问题

This commit is contained in:
arvinxx
2023-07-16 17:02:30 +08:00
parent 8415a3025b
commit a3d972433f
7 changed files with 61 additions and 37 deletions

View File

@@ -3,8 +3,9 @@ import { App, ConfigProvider } from 'antd';
import 'antd/dist/reset.css';
import Zh_CN from 'antd/locale/zh_CN';
import { PropsWithChildren, useEffect } from 'react';
import { useSessionStore } from 'src/store/session';
import { useSessionStore } from '@/store/session';
import { useSettings } from '@/store/settings';
import { GlobalStyle } from '@/styles';
import { useStyles } from './style';
@@ -23,6 +24,7 @@ export default ({ children }: PropsWithChildren) => {
useEffect(() => {
// refs: https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md#hashydrated
useSessionStore.persist.rehydrate();
useSettings.persist.rehydrate();
}, []);
return (

View File

@@ -19,7 +19,7 @@ const ChatInput = () => {
(s) => [
chatSelectors.totalTokenCount(s),
agentSelectors.currentAgentModel(s),
s.sendMessage,
s.createOrSendMsg,
s.clearMessage,
],
shallow,

View File

@@ -2,8 +2,9 @@ import { createStyles } from 'antd-style';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';
import ChatInput from '@/pages/chat/[id]/Conversation/Input';
import ChatList from './ChatList';
import ChatInput from './Input';
const useStyles = createStyles(({ css, token }) => ({
input: css`

View File

@@ -1,46 +1,43 @@
import isEqual from 'fast-deep-equal';
import Head from 'next/head';
import { useRouter } from 'next/router';
import { PropsWithChildren, memo, useEffect } from 'react';
import { Flexbox } from 'react-layout-kit';
import { shallow } from 'zustand/shallow';
import { sessionSelectors, useSessionStore } from '@/store/session';
import { useSessionStore } from '@/store/session';
import { useSettings } from '@/store/settings';
import Sidebar from '../Sidebar';
import { Sessions } from './SessionList';
const ChatLayout = memo<PropsWithChildren>(({ children }) => {
const [title] = useSessionStore((s) => {
const context = sessionSelectors.currentSession(s);
return [context?.meta.title];
}, isEqual);
useEffect(() => {
useSettings.persist.rehydrate();
useSettings.setState({ sidebarKey: 'chat' });
}, []);
const [activeSession] = useSessionStore((s) => {
return [s.activeSession];
}, shallow);
const router = useRouter();
const { id } = router.query;
useEffect(() => {
if (typeof id === 'string') {
useSessionStore.setState({ activeId: id });
const hasRehydrated = useSessionStore.persist.hasHydrated();
// 只有当水合完毕后,才能正常去激活会话
if (typeof id === 'string' && hasRehydrated) {
activeSession(id);
}
}, [id]);
useEffect(() => {
const hasRehydrated = useSettings.persist.hasHydrated();
if (hasRehydrated) {
useSettings.setState({ sidebarKey: 'chat' });
}
}, []);
return (
<>
<Head>
<title>{title ? `${title} - LobeChat` : 'LobeChat'}</title>
</Head>
<Flexbox horizontal width={'100%'}>
<Sidebar />
<Sessions />
{children}
</Flexbox>
</>
<Flexbox horizontal width={'100%'}>
<Sidebar />
<Sessions />
{children}
</Flexbox>
);
});

View File

@@ -14,7 +14,7 @@ const persistOptions: PersistOptions<SessionStore, SessionPersist> = {
// 手动控制 Hydration ,避免 ssr 报错
skipHydration: true,
version: 0,
// version: Migration.targetVersion,
};

View File

@@ -12,6 +12,8 @@ const LOADING_FLAT = '...';
export interface ChatAction {
clearMessage: () => void;
createOrSendMsg: (text: string) => Promise<void>;
deleteMessage: (id: string) => void;
/**
@@ -20,15 +22,14 @@ export interface ChatAction {
* @returns void
*/
dispatchMessage: (payload: MessageDispatch) => void;
generateMessage: (messages: ChatMessage[], options: FetchSSEOptions) => Promise<void>;
/**
* @title 处理消息编辑
* @param index - 消息索引或空
* @returns void
*/
handleMessageEditing: (messageId: string | undefined) => void;
/**
* @title 重发消息
* @param index - 消息索引
@@ -52,6 +53,20 @@ export const createChatSlice: StateCreator<
get().dispatchMessage({ type: 'resetMessages' });
},
createOrSendMsg: async (message) => {
if (!message) return;
console.log(message);
const { sendMessage, createSession } = get();
const session = sessionSelectors.currentSession(get());
if (!session) {
await createSession();
}
sendMessage(message);
},
deleteMessage: (id) => {
get().dispatchMessage({ id, type: 'deleteMessage' });
},

View File

@@ -9,18 +9,19 @@ import { uuid } from '@/utils/uuid';
import { SessionDispatch, sessionsReducer } from './reducers/session';
export interface SessionAction {
activeSession: (sessionId: string) => void;
/**
* @title 添加会话
* @param session - 会话信息
* @returns void
*/
createSession: () => Promise<void>;
createSession: () => Promise<string>;
/**
* 分发聊天记录
* @param payload - 聊天记录
*/
dispatchSession: (payload: SessionDispatch) => void;
/**
* @title 删除会话
* @param index - 会话索引
@@ -33,7 +34,7 @@ export interface SessionAction {
* @param sessionId - 会话索引
* @returns void
*/
switchSession: (sessionId?: string | 'new') => void;
switchSession: (sessionId?: string | 'new') => Promise<void>;
/**
* 生成压缩后的消息
@@ -48,6 +49,10 @@ export const createSessionSlice: StateCreator<
[],
SessionAction
> = (set, get) => ({
activeSession: (sessionId) => {
set({ activeId: sessionId });
},
createSession: async () => {
const { dispatchSession, switchSession } = get();
@@ -73,7 +78,9 @@ export const createSessionSlice: StateCreator<
dispatchSession({ session: newSession, type: 'addSession' });
switchSession(newSession.id);
await switchSession(newSession.id);
return newSession.id;
},
dispatchSession: (payload) => {
@@ -92,13 +99,15 @@ export const createSessionSlice: StateCreator<
}
},
switchSession: (sessionId) => {
switchSession: async (sessionId) => {
if (get().activeId === sessionId) return;
set({ activeId: sessionId });
if (sessionId) {
get().activeSession(sessionId);
}
// 新会话
Router.push(`/chat/${sessionId}`);
await Router.push(`/chat/${sessionId}`);
},
// genShareUrl: () => {