History

Prevent unrelated client settings rerenders

Cursor Agent committed 4 months ago

Commit 909cbf71 parent fdca1543 files · +26 −2Browse files

Unified · Split

3 files
  1. apps/web/package.json +2 −0
  2. apps/web/src/hooks/useSettings.ts +13 −2
  3. pnpm-lock.yaml +11 −0
apps/web/package.json+2−0
@@ -46,6 +46,7 @@ · 45 unmodified lines
4646 "remark-breaks": "^4.0.0",
4747 "remark-gfm": "^4.0.1",
4848 "tailwind-merge": "^3.4.0",
49+ "use-sync-external-store": "^1.6.0",
4950 "zustand": "^5.0.11"
5051 },
5152 "devDependencies": {
@@ -57,6 +58,7 @@ · 5 unmodified lines
5758 "@types/babel__core": "^7.20.5",
5859 "@types/react": "~19.2.14",
5960 "@types/react-dom": "~19.2.3",
61+ "@types/use-sync-external-store": "^1.5.0",
6062 "@vercel/config": "^0.3.0",
6163 "@vitejs/plugin-react": "^6.0.0",
6264 "babel-plugin-react-compiler": "1.0.0",
apps/web/src/hooks/useSettings.ts+13−2
@@ -29,6 +29,8 @@ import * as Struct from "effect/Struct"; · 28 unmodified lines
2929 import { primaryServerSettingsAtom, serverEnvironment } from "~/state/server";
3030 import { usePrimaryEnvironment } from "~/state/environments";
3131 import { useAtomCommand } from "~/state/use-atom-command";
32+import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";
33+import { shallow } from "zustand/shallow";
3234
3335 const CLIENT_SETTINGS_PERSISTENCE_ERROR_SCOPE = "[CLIENT_SETTINGS]";
3436
@@ -55,6 +57,10 @@ function getClientSettingsSnapshot(): ClientSettings { · 20 unmodified lines
5557 return clientSettingsSnapshot;
5658 }
5759
60+function selectClientSettings(settings: ClientSettings): ClientSettings {
61+ return settings;
62+}
63+
5864 function replaceClientSettingsSnapshot(settings: ClientSettings): void {
5965 clientSettingsSnapshot = settings;
6066 emitClientSettingsChange();
@@ -214,8 +220,13 @@ function useMergedSettings<T>( · 153 unmodified lines
214220 export function useClientSettings<T = ClientSettings>(
215221 selector?: (settings: ClientSettings) => T,
216222 ): T {
217− const settings = useClientSettingsValue();
218− return useMemo(() => (selector ? selector(settings) : (settings as T)), [selector, settings]);
223+ return useSyncExternalStoreWithSelector(
224+ subscribeClientSettings,
225+ getClientSettingsSnapshot,
226+ () => DEFAULT_CLIENT_SETTINGS,
227+ selector ?? (selectClientSettings as (settings: ClientSettings) => T),
228+ selector ? shallow : Object.is,
229+ );
219230 }
220231
221232 /** Read current settings for one environment, merged with client-local preferences. */
pnpm-lock.yaml+11−0
@@ -607,6 +607,9 @@ importers: · 606 unmodified lines
607607 tailwind-merge:
608608 specifier: ^3.4.0
609609 version: 3.6.0
610+ use-sync-external-store:
611+ specifier: ^1.6.0
612+ version: 1.6.0(react@19.2.6)
610613 zustand:
611614 specifier: ^5.0.11
612615 version: 5.0.14(@types/react@19.2.16)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6))
@@ -635,6 +638,9 @@ importers: · 22 unmodified lines
635638 '@types/react-dom':
636639 specifier: ~19.2.3
637640 version: 19.2.3(@types/react@19.2.16)
641+ '@types/use-sync-external-store':
642+ specifier: ^1.5.0
643+ version: 1.5.0
638644 '@vercel/config':
639645 specifier: ^0.3.0
640646 version: 0.3.0
@@ -4921,6 +4927,9 @@ packages: · 4280 unmodified lines
49214927 '@types/unist@3.0.3':
49224928 resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
49234929
4930+ '@types/use-sync-external-store@1.5.0':
4931+ resolution: {integrity: sha512-5dyB8nLC/qogMrlCizZnYWQTA4lnb/v+It+sqNl5YnSRAPMlIqY/X0Xn+gZw8vOL+TgTTr28VEbn3uf8fUtAkw==}
4932+
49244933 '@types/ws@8.18.1':
49254934 resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
49264935
@@ -14947,6 +14956,8 @@ snapshots: · 10020 unmodified lines
1494714956
1494814957 '@types/unist@3.0.3': {}
1494914958
14959+ '@types/use-sync-external-store@1.5.0': {}
14960+
1495014961 '@types/ws@8.18.1':
1495114962 dependencies:
1495214963 '@types/node': 24.12.4