mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-15 20:16:02 +00:00
🐛 fix: slove swr mutate not work in Cache Provider (#10895)
fix: slove swr mutate not work in Cache Provider
This commit is contained in:
@@ -1,12 +1,28 @@
|
||||
'use client';
|
||||
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import React, { PropsWithChildren, useState } from 'react';
|
||||
import { SWRConfig } from 'swr';
|
||||
import React, { PropsWithChildren, useEffect, useState } from 'react';
|
||||
import { SWRConfig, useSWRConfig } from 'swr';
|
||||
|
||||
import { setScopedMutate } from '@/libs/swr';
|
||||
import { swrCacheProvider } from '@/libs/swr/localStorageProvider';
|
||||
import { lambdaQuery, lambdaQueryClient } from '@/libs/trpc/client';
|
||||
|
||||
/**
|
||||
* Initialize scoped mutate for use outside React components (e.g., Zustand stores)
|
||||
* This component must be rendered inside SWRConfig to access the scoped mutate
|
||||
*/
|
||||
const SWRMutateInitializer = ({ children }: PropsWithChildren) => {
|
||||
const { mutate } = useSWRConfig();
|
||||
|
||||
useEffect(() => {
|
||||
setScopedMutate(mutate);
|
||||
}, [mutate]);
|
||||
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
const QueryProvider = ({ children }: PropsWithChildren) => {
|
||||
const [queryClient] = useState(() => new QueryClient());
|
||||
// Cast required because pnpm installs separate QueryClient type instances for trpc and app
|
||||
@@ -19,9 +35,11 @@ const QueryProvider = ({ children }: PropsWithChildren) => {
|
||||
|
||||
return (
|
||||
<SWRConfig value={{ provider }}>
|
||||
<lambdaQuery.Provider client={lambdaQueryClient} queryClient={providerQueryClient}>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
</lambdaQuery.Provider>
|
||||
<SWRMutateInitializer>
|
||||
<lambdaQuery.Provider client={lambdaQueryClient} queryClient={providerQueryClient}>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
</lambdaQuery.Provider>
|
||||
</SWRMutateInitializer>
|
||||
</SWRConfig>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -96,3 +96,6 @@ export type SWRefreshMethod<T> = <A extends (...args: any[]) => Promise<any>>(
|
||||
|
||||
// 导出带自动同步功能的 hook
|
||||
export { useClientDataSWRWithSync } from './useClientDataSWRWithSync';
|
||||
|
||||
// 导出 scoped mutate(用于自定义 cache provider 场景)
|
||||
export { mutate, setScopedMutate } from './mutate';
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Scoped SWR Mutate
|
||||
*
|
||||
* When using a custom cache provider with SWRConfig, the global `mutate` from 'swr'
|
||||
* becomes a no-op because it can't access the scoped cache.
|
||||
*
|
||||
* This module provides a scoped mutate function that works with custom cache providers.
|
||||
* The mutate function is initialized when the SWRConfig component mounts.
|
||||
*
|
||||
* @see https://github.com/vercel/swr/issues/2799
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Instead of:
|
||||
* import { mutate } from 'swr';
|
||||
*
|
||||
* // Use:
|
||||
* import { mutate } from '@/libs/swr';
|
||||
* ```
|
||||
*/
|
||||
import type { ScopedMutator } from 'swr/_internal';
|
||||
|
||||
// Global scoped mutate reference, set when SWRConfig mounts
|
||||
let scopedMutate: ScopedMutator | null = null;
|
||||
|
||||
/**
|
||||
* Set the scoped mutate function from SWRConfig
|
||||
* Called internally by SWRProvider on mount
|
||||
*/
|
||||
export const setScopedMutate = (m: ScopedMutator) => {
|
||||
scopedMutate = m;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scoped mutate function that works with custom cache providers
|
||||
*
|
||||
* Use this instead of `import { mutate } from 'swr'` when using localStorage cache provider
|
||||
*/
|
||||
export const mutate: ScopedMutator = ((key: any, data?: any, opts?: any) => {
|
||||
if (!scopedMutate) {
|
||||
console.warn('[SWR] Scoped mutate not initialized, this may cause cache sync issues');
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return scopedMutate(key, data, opts);
|
||||
}) as ScopedMutator;
|
||||
@@ -1,12 +1,12 @@
|
||||
import { getSingletonAnalyticsOptional } from '@lobehub/analytics';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { produce } from 'immer';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { MESSAGE_CANCEL_FLAT } from '@/const/message';
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { CreateAgentParams, CreateAgentResult, agentService } from '@/services/agent';
|
||||
import { getUserStoreState } from '@/store/user';
|
||||
import { userProfileSelectors } from '@/store/user/selectors';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { KnowledgeItem } from '@lobechat/types';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { agentService } from '@/services/agent';
|
||||
|
||||
import type { AgentStore } from '../../store';
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { AgentGroupDetail } from '@lobechat/types';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { produce } from 'immer';
|
||||
import { mutate } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import type { ChatGroupItem } from '@/database/schemas/chatGroup';
|
||||
import { useClientDataSWRWithSync } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWRWithSync } from '@/libs/swr';
|
||||
import { chatGroupService } from '@/services/chatGroup';
|
||||
import { getAgentStoreState } from '@/store/agent';
|
||||
import { ChatGroupStore } from '@/store/agentGroup/store';
|
||||
|
||||
@@ -5,10 +5,10 @@ import {
|
||||
CreateAiModelParams,
|
||||
ToggleAiModelEnableParams,
|
||||
} from 'model-bank';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { aiModelService } from '@/services/aiModel';
|
||||
import { AiInfraStore } from '@/store/aiInfra/store';
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ import {
|
||||
ModelParamsSchema,
|
||||
Pricing,
|
||||
} from 'model-bank';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { aiProviderService } from '@/services/aiProvider';
|
||||
import { AiInfraStore } from '@/store/aiInfra/store';
|
||||
import { useUserStore } from '@/store/user';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { parse } from '@lobechat/conversation-flow';
|
||||
import { ConversationContext, UIChatMessage } from '@lobechat/types';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { mutate } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { mutate } from '@/libs/swr';
|
||||
import { ChatStore } from '@/store/chat/store';
|
||||
|
||||
import { MessageMapKeyInput, messageMapKey } from '../../../utils/messageMapKey';
|
||||
|
||||
@@ -4,10 +4,10 @@ import { LOADING_FLAT } from '@lobechat/const';
|
||||
import { chainSummaryTitle } from '@lobechat/prompts';
|
||||
import { CreateMessageParams, IThreadType, ThreadItem, UIChatMessage } from '@lobechat/types';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { chatService } from '@/services/chat';
|
||||
import { threadService } from '@/services/thread';
|
||||
import { threadSelectors } from '@/store/chat/selectors';
|
||||
|
||||
@@ -5,12 +5,12 @@ import { chainSummaryTitle } from '@lobechat/prompts';
|
||||
import { TraceNameMap, UIChatMessage } from '@lobechat/types';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { t } from 'i18next';
|
||||
import useSWR, { SWRResponse, mutate } from 'swr';
|
||||
import useSWR, { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { message } from '@/components/AntdStaticMethods';
|
||||
import { LOADING_FLAT } from '@/const/message';
|
||||
import { useClientDataSWRWithSync } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWRWithSync } from '@/libs/swr';
|
||||
import { chatService } from '@/services/chat';
|
||||
import { messageService } from '@/services/message';
|
||||
import { topicService } from '@/services/topic';
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { NetworkProxySettings, ShortcutUpdateResult } from '@lobechat/electron-client-ipc';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import useSWR, { SWRResponse, mutate } from 'swr';
|
||||
import useSWR, { SWRResponse } from 'swr';
|
||||
import type { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { mutate } from '@/libs/swr';
|
||||
import { desktopSettingsService } from '@/services/electron/settings';
|
||||
|
||||
import type { ElectronStore } from '../store';
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { DataSyncConfig } from '@lobechat/electron-client-ipc';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import useSWR, { SWRResponse, mutate } from 'swr';
|
||||
import useSWR, { SWRResponse } from 'swr';
|
||||
import type { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { mutate } from '@/libs/swr';
|
||||
import { remoteServerService } from '@/services/electron/remoteServer';
|
||||
|
||||
import { initialState } from '../initialState';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { buildFolderTree, sanitizeFolderName, topologicalSortFolders } from '@lobechat/utils';
|
||||
import pMap from 'p-map';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { FILE_UPLOAD_BLACKLIST, MAX_UPLOAD_FILE_COUNT } from '@/const/file';
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { FileService, fileService } from '@/services/file';
|
||||
import { ragService } from '@/services/rag';
|
||||
import {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { mutate } from 'swr';
|
||||
import type { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import type { SidebarAgentItem, SidebarAgentListResponse } from '@/database/repositories/home';
|
||||
import { useClientDataSWR, useClientDataSWRWithSync } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR, useClientDataSWRWithSync } from '@/libs/swr';
|
||||
import { homeService } from '@/services/home';
|
||||
import type { HomeStore } from '@/store/home/store';
|
||||
import { setNamespace } from '@/utils/storeDebug';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { isEqual } from 'es-toolkit/compat';
|
||||
import { useRef } from 'react';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand';
|
||||
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { GetGenerationStatusResult } from '@/server/routers/lambda/generation';
|
||||
import { generationService } from '@/services/generation';
|
||||
import { generationBatchService } from '@/services/generationBatch';
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { chainSummaryGenerationTitle } from '@lobechat/prompts';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { LOADING_FLAT } from '@/const/message';
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { UpdateTopicValue } from '@/server/routers/lambda/generationTopic';
|
||||
import { chatService } from '@/services/chat';
|
||||
import { generationTopicService } from '@/services/generationTopic';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { knowledgeBaseService } from '@/services/knowledgeBase';
|
||||
import { KnowledgeBaseStore } from '@/store/knowledgeBase/store';
|
||||
import { CreateKnowledgeBaseParams, KnowledgeBaseItem } from '@/types/knowledgeBase';
|
||||
|
||||
@@ -4,11 +4,11 @@ import {
|
||||
RAGEvalDataSetItem,
|
||||
insertEvalDatasetRecordSchema,
|
||||
} from '@lobechat/types';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { notification } from '@/components/AntdStaticMethods';
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { ragEvalService } from '@/services/ragEval';
|
||||
import { KnowledgeBaseStore } from '@/store/knowledgeBase/store';
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { CreateNewEvalEvaluation, RAGEvalDataSetItem } from '@lobechat/types';
|
||||
import { SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { ragEvalService } from '@/services/ragEval';
|
||||
import { KnowledgeBaseStore } from '@/store/knowledgeBase/store';
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { getSingletonAnalyticsOptional } from '@lobehub/analytics';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { t } from 'i18next';
|
||||
import useSWR, { SWRResponse, mutate } from 'swr';
|
||||
import useSWR, { SWRResponse } from 'swr';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { message } from '@/components/AntdStaticMethods';
|
||||
import { DEFAULT_AGENT_LOBE_SESSION, INBOX_SESSION_ID } from '@/const/session';
|
||||
import { DEFAULT_CHAT_GROUP_CHAT_CONFIG } from '@/const/settings';
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { chatGroupService } from '@/services/chatGroup';
|
||||
import { sessionService } from '@/services/session';
|
||||
import { getChatGroupStoreState } from '@/store/agentGroup';
|
||||
|
||||
@@ -2,10 +2,11 @@ import { LobeTool } from '@lobechat/types';
|
||||
import { uniqBy } from 'es-toolkit/compat';
|
||||
import { t } from 'i18next';
|
||||
import { produce } from 'immer';
|
||||
import useSWR, { SWRResponse, mutate } from 'swr';
|
||||
import useSWR, { SWRResponse } from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { notification } from '@/components/AntdStaticMethods';
|
||||
import { mutate } from '@/libs/swr';
|
||||
import { pluginService } from '@/services/plugin';
|
||||
import { toolService } from '@/services/tool';
|
||||
import { globalHelpers } from '@/store/global/helpers';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { isDesktop } from '@lobechat/const';
|
||||
import { getSingletonAnalyticsOptional } from '@lobehub/analytics';
|
||||
import useSWR, { SWRResponse, mutate } from 'swr';
|
||||
import useSWR, { SWRResponse } from 'swr';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { DEFAULT_PREFERENCE } from '@/const/user';
|
||||
import { useOnlyFetchOnceSWR } from '@/libs/swr';
|
||||
import { mutate, useOnlyFetchOnceSWR } from '@/libs/swr';
|
||||
import { userService } from '@/services/user';
|
||||
import type { UserStore } from '@/store/user';
|
||||
import type { GlobalServerConfig } from '@/types/serverConfig';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import isEqual from 'fast-deep-equal';
|
||||
import { type SWRResponse, mutate } from 'swr';
|
||||
import type { SWRResponse } from 'swr';
|
||||
import useSWR from 'swr';
|
||||
import { StateCreator } from 'zustand/vanilla';
|
||||
|
||||
import { useClientDataSWR } from '@/libs/swr';
|
||||
import { mutate, useClientDataSWR } from '@/libs/swr';
|
||||
import { userMemoryService } from '@/services/userMemory';
|
||||
import { LayersEnum } from '@/types/userMemory';
|
||||
import type { RetrieveMemoryParams, RetrieveMemoryResult } from '@/types/userMemory';
|
||||
|
||||
Reference in New Issue
Block a user