mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-02-06 11:01:13 +08:00
fix: memoize provider selectors to prevent infinite re-renders (#12550)
The normalizeProvider() calls inside useAppSelector callbacks were
creating new object references on every render, causing infinite
re-render loops in components that depend on provider objects.
This fix uses createSelector from Redux Toolkit to properly memoize
the normalized providers, preventing unnecessary re-renders in:
- GithubCopilotSettings (useEffect depends on provider)
- Painting pages (useAllProviders returns new array each render)
Fixes the "Maximum update depth exceeded" error introduced in 8186d4fa.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
f84941f91f
commit
1f209dc280
@ -1,7 +1,7 @@
|
||||
import { createSelector } from '@reduxjs/toolkit'
|
||||
import { CHERRYAI_PROVIDER } from '@renderer/config/providers'
|
||||
import { getDefaultProvider } from '@renderer/services/AssistantService'
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import { type RootState, useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import {
|
||||
addModel,
|
||||
addProvider,
|
||||
@ -14,6 +14,7 @@ import {
|
||||
import type { Assistant, Model, Provider } from '@renderer/types'
|
||||
import { isSystemProvider } from '@renderer/types'
|
||||
import { withoutTrailingSlash } from '@renderer/utils/api'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { useDefaultModel } from './useAssistant'
|
||||
|
||||
@ -28,13 +29,27 @@ function normalizeProvider<T extends Provider>(provider: T): T {
|
||||
}
|
||||
}
|
||||
|
||||
const selectEnabledProviders = createSelector(
|
||||
(state) => state.llm.providers,
|
||||
(providers) =>
|
||||
providers
|
||||
.map(normalizeProvider)
|
||||
.filter((p) => p.enabled)
|
||||
.concat(CHERRYAI_PROVIDER)
|
||||
const selectProviders = (state: RootState) => state.llm.providers
|
||||
|
||||
const selectEnabledProviders = createSelector(selectProviders, (providers) =>
|
||||
providers
|
||||
.map(normalizeProvider)
|
||||
.filter((p) => p.enabled)
|
||||
.concat(CHERRYAI_PROVIDER)
|
||||
)
|
||||
|
||||
const selectSystemProviders = createSelector(selectProviders, (providers) =>
|
||||
providers.filter((p) => isSystemProvider(p)).map(normalizeProvider)
|
||||
)
|
||||
|
||||
const selectUserProviders = createSelector(selectProviders, (providers) =>
|
||||
providers.filter((p) => !isSystemProvider(p)).map(normalizeProvider)
|
||||
)
|
||||
|
||||
const selectAllProviders = createSelector(selectProviders, (providers) => providers.map(normalizeProvider))
|
||||
|
||||
const selectAllProvidersWithCherryAI = createSelector(selectProviders, (providers) =>
|
||||
[...providers, CHERRYAI_PROVIDER].map(normalizeProvider)
|
||||
)
|
||||
|
||||
export function useProviders() {
|
||||
@ -51,25 +66,20 @@ export function useProviders() {
|
||||
}
|
||||
|
||||
export function useSystemProviders() {
|
||||
return useAppSelector((state) => state.llm.providers.filter((p) => isSystemProvider(p)).map(normalizeProvider))
|
||||
return useAppSelector(selectSystemProviders)
|
||||
}
|
||||
|
||||
export function useUserProviders() {
|
||||
return useAppSelector((state) => state.llm.providers.filter((p) => !isSystemProvider(p)).map(normalizeProvider))
|
||||
return useAppSelector(selectUserProviders)
|
||||
}
|
||||
|
||||
export function useAllProviders() {
|
||||
return useAppSelector((state) => state.llm.providers.map(normalizeProvider))
|
||||
return useAppSelector(selectAllProviders)
|
||||
}
|
||||
|
||||
export function useProvider(id: string) {
|
||||
const provider =
|
||||
useAppSelector((state) =>
|
||||
state.llm.providers
|
||||
.concat([CHERRYAI_PROVIDER])
|
||||
.map(normalizeProvider)
|
||||
.find((p) => p.id === id)
|
||||
) || getDefaultProvider()
|
||||
const allProviders = useAppSelector(selectAllProvidersWithCherryAI)
|
||||
const provider = useMemo(() => allProviders.find((p) => p.id === id) || getDefaultProvider(), [allProviders, id])
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
return {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user