perf(context): memoize providers + system-settings context values

Both provider components built their context `value` as a fresh object literal
each render (providers-provider also re-sorted into a new array and recreated
its setter), forcing every consumer to re-render on each provider render.
Memoize the sorted array, the setter, and both value objects — the two
non-memoized outliers among the app's context providers. No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sergey Kozyrenko
2026-07-10 13:10:14 +07:00
co-authored by Claude Opus 4.8
parent 605b271214
commit 933a80147e
2 changed files with 21 additions and 19 deletions
+12 -9
View File
@@ -1,5 +1,5 @@
import { useQuery } from '@apollo/client/react';
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import type { Provider } from '@/models/provider';
@@ -28,7 +28,7 @@ export function ProvidersProvider({ children }: ProvidersProviderProps) {
skip: !isAuthenticated(),
});
const providers = sortProviders(providersData?.providers || []);
const providers = useMemo(() => sortProviders(providersData?.providers || []), [providersData?.providers]);
const [selectedProviderName, setSelectedProviderName] = useState<null | string>(() => {
return localStorage.getItem(SELECTED_PROVIDER_KEY);
@@ -56,15 +56,18 @@ export function ProvidersProvider({ children }: ProvidersProviderProps) {
}
}, [selectedProvider]);
const setSelectedProvider = (provider: Provider) => {
const setSelectedProvider = useCallback((provider: Provider) => {
setSelectedProviderName(provider.name);
};
}, []);
const value = {
providers,
selectedProvider,
setSelectedProvider,
};
const value = useMemo(
() => ({
providers,
selectedProvider,
setSelectedProvider,
}),
[providers, selectedProvider, setSelectedProvider],
);
return <ProvidersContext.Provider value={value}>{children}</ProvidersContext.Provider>;
}
@@ -1,7 +1,7 @@
import type { ReactNode } from 'react';
import { useQuery } from '@apollo/client/react';
import { createContext, use } from 'react';
import { createContext, use, useMemo } from 'react';
import type { SettingsFragmentFragment } from '@/graphql/types';
@@ -22,16 +22,15 @@ export function SystemSettingsProvider({ children }: { children: ReactNode }) {
skip: !isAuthenticated(),
});
return (
<SystemSettingsContext
value={{
isLoading: loading,
settings: settingsData?.settings ?? null,
}}
>
{children}
</SystemSettingsContext>
const value = useMemo<SettingsContextType>(
() => ({
isLoading: loading,
settings: settingsData?.settings ?? null,
}),
[loading, settingsData?.settings],
);
return <SystemSettingsContext value={value}>{children}</SystemSettingsContext>;
}
export function useSystemSettings() {