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
46 "remark-breaks": "^4.0.0",46 "remark-breaks": "^4.0.0",
47 "remark-gfm": "^4.0.1",47 "remark-gfm": "^4.0.1",
48 "tailwind-merge": "^3.4.0",48 "tailwind-merge": "^3.4.0",
49 "use-sync-external-store": "^1.6.0",
49 "zustand": "^5.0.11"50 "zustand": "^5.0.11"
50 },51 },
51 "devDependencies": {52 "devDependencies": {
@@ -57,6 +58,7 @@ · 5 unmodified lines
57 "@types/babel__core": "^7.20.5",58 "@types/babel__core": "^7.20.5",
58 "@types/react": "~19.2.14",59 "@types/react": "~19.2.14",
59 "@types/react-dom": "~19.2.3",60 "@types/react-dom": "~19.2.3",
61 "@types/use-sync-external-store": "^1.5.0",
60 "@vercel/config": "^0.3.0",62 "@vercel/config": "^0.3.0",
61 "@vitejs/plugin-react": "^6.0.0",63 "@vitejs/plugin-react": "^6.0.0",
62 "babel-plugin-react-compiler": "1.0.0",64 "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
29import { primaryServerSettingsAtom, serverEnvironment } from "~/state/server";29import { primaryServerSettingsAtom, serverEnvironment } from "~/state/server";
30import { usePrimaryEnvironment } from "~/state/environments";30import { usePrimaryEnvironment } from "~/state/environments";
31import { useAtomCommand } from "~/state/use-atom-command";31import { useAtomCommand } from "~/state/use-atom-command";
32import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";
33import { shallow } from "zustand/shallow";
32 34
33const CLIENT_SETTINGS_PERSISTENCE_ERROR_SCOPE = "[CLIENT_SETTINGS]";35const CLIENT_SETTINGS_PERSISTENCE_ERROR_SCOPE = "[CLIENT_SETTINGS]";
34 36
@@ -55,6 +57,10 @@ function getClientSettingsSnapshot(): ClientSettings { · 20 unmodified lines
55 return clientSettingsSnapshot;57 return clientSettingsSnapshot;
56}58}
57 59
60function selectClientSettings(settings: ClientSettings): ClientSettings {
61 return settings;
62}
63
58function replaceClientSettingsSnapshot(settings: ClientSettings): void {64function replaceClientSettingsSnapshot(settings: ClientSettings): void {
59 clientSettingsSnapshot = settings;65 clientSettingsSnapshot = settings;
60 emitClientSettingsChange();66 emitClientSettingsChange();
@@ -214,8 +220,13 @@ function useMergedSettings<T>( · 153 unmodified lines
214export function useClientSettings<T = ClientSettings>(220export function useClientSettings<T = ClientSettings>(
215 selector?: (settings: ClientSettings) => T,221 selector?: (settings: ClientSettings) => T,
216): T {222): T {
217 const settings = useClientSettingsValue();223 return useSyncExternalStoreWithSelector(
218 return useMemo(() => (selector ? selector(settings) : (settings as T)), [selector, settings]);224 subscribeClientSettings,
225 getClientSettingsSnapshot,
226 () => DEFAULT_CLIENT_SETTINGS,
227 selector ?? (selectClientSettings as (settings: ClientSettings) => T),
228 selector ? shallow : Object.is,
229 );
219}230}
220 231
221/** Read current settings for one environment, merged with client-local preferences. */232/** Read current settings for one environment, merged with client-local preferences. */
pnpm-lock.yaml+11−0
@@ -607,6 +607,9 @@ importers: · 606 unmodified lines
607 tailwind-merge:607 tailwind-merge:
608 specifier: ^3.4.0608 specifier: ^3.4.0
609 version: 3.6.0609 version: 3.6.0
610 use-sync-external-store:
611 specifier: ^1.6.0
612 version: 1.6.0(react@19.2.6)
610 zustand:613 zustand:
611 specifier: ^5.0.11614 specifier: ^5.0.11
612 version: 5.0.14(@types/react@19.2.16)(react@19.2.6)(use-sync-external-store@1.6.0(react@19.2.6))615 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
635 '@types/react-dom':638 '@types/react-dom':
636 specifier: ~19.2.3639 specifier: ~19.2.3
637 version: 19.2.3(@types/react@19.2.16)640 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
638 '@vercel/config':644 '@vercel/config':
639 specifier: ^0.3.0645 specifier: ^0.3.0
640 version: 0.3.0646 version: 0.3.0
@@ -4921,6 +4927,9 @@ packages: · 4280 unmodified lines
4921 '@types/unist@3.0.3':4927 '@types/unist@3.0.3':
4922 resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}4928 resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
4923 4929
4930 '@types/use-sync-external-store@1.5.0':
4931 resolution: {integrity: sha512-5dyB8nLC/qogMrlCizZnYWQTA4lnb/v+It+sqNl5YnSRAPMlIqY/X0Xn+gZw8vOL+TgTTr28VEbn3uf8fUtAkw==}
4932
4924 '@types/ws@8.18.1':4933 '@types/ws@8.18.1':
4925 resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}4934 resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
4926 4935
@@ -14947,6 +14956,8 @@ snapshots: · 10020 unmodified lines
14947 14956
14948 '@types/unist@3.0.3': {}14957 '@types/unist@3.0.3': {}
14949 14958
14959 '@types/use-sync-external-store@1.5.0': {}
14960
14950 '@types/ws@8.18.1':14961 '@types/ws@8.18.1':
14951 dependencies:14962 dependencies:
14952 '@types/node': 24.12.414963 '@types/node': 24.12.4