From bfde8e60c2d193efbb88ca4374591c0165100c97 Mon Sep 17 00:00:00 2001 From: Tomasz Zawadzki Date: Mon, 31 Aug 2026 23:03:13 +0200 Subject: [PATCH] Unblock React Compiler for 5 components by removing render-phase mutation (#11543) Co-authored-by: Claude Opus 5 (1M context) Co-authored-by: Samuel Newman --- src/analytics/utils.ts | 10 +++-- src/components/Composer/index.tsx | 4 +- src/components/dialogs/nuxs/index.tsx | 9 +++-- src/components/moderation/ContentHider.tsx | 47 +++++++++------------- src/state/session/index.tsx | 8 ++-- src/view/com/pager/TabBar.tsx | 2 +- 6 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/analytics/utils.ts b/src/analytics/utils.ts index b20b3719c9..af1ef84070 100644 --- a/src/analytics/utils.ts +++ b/src/analytics/utils.ts @@ -11,14 +11,18 @@ import { * Thin `useMemo` wrapper that marks the metadata as memoized and provides a * type guard. */ -export function useMeta(metadata?: MergeableMetadata) { - const m = useMemo(() => metadata, [metadata]) - if (!m) return +function markMemoized(m: T): T { // @ts-expect-error m.__meta = true return m } +export function useMeta(metadata?: MergeableMetadata) { + const m = useMemo(() => metadata, [metadata]) + if (!m) return + return markMemoized(m) +} + export function accountToSessionMetadata( account: SessionAccount | undefined, ): SessionMetadata | undefined { diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index b2266db5a1..eb37771415 100644 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -362,9 +362,9 @@ export function Composer({ onKeyPress={IS_WEB ? onKeyPressWeb : undefined} onScroll={e => { if (IS_WEB) { - inputScrollSharedValue.value = (e.target as any).scrollTop + inputScrollSharedValue.set((e.target as any).scrollTop) } else { - inputScrollSharedValue.value = e.nativeEvent.contentOffset.y + inputScrollSharedValue.set(e.nativeEvent.contentOffset.y) } }} // @ts-expect-error web only diff --git a/src/components/dialogs/nuxs/index.tsx b/src/components/dialogs/nuxs/index.tsx index e8b6789120..030dc79dff 100644 --- a/src/components/dialogs/nuxs/index.tsx +++ b/src/components/dialogs/nuxs/index.tsx @@ -116,14 +116,15 @@ function Inner({ setActiveNux(undefined) }, [activeNux, setActiveNux]) - if (__DEV__ && typeof window !== 'undefined') { - // @ts-expect-error + useEffect(() => { + if (!__DEV__ || typeof window === 'undefined') return + // @ts-expect-error debug only window.clearNuxDialog = (id: Nux) => { - if (!__DEV__ || !id) return + if (!id) return resetNuxs([id]) unsnooze() } - } + }, [resetNuxs]) useEffect(() => { if (snoozed) return // comment this out to test diff --git a/src/components/moderation/ContentHider.tsx b/src/components/moderation/ContentHider.tsx index c33c17a881..2bc50a8598 100644 --- a/src/components/moderation/ContentHider.tsx +++ b/src/components/moderation/ContentHider.tsx @@ -101,35 +101,28 @@ function ContentHiderActive({ } } + const selfBlurCauses = [] let hasAdultContentLabel = false - const selfBlurNames = modui.blurs - .filter(cause => { - if (cause.type !== 'label') { - return false - } - if (cause.source.type !== 'user') { - return false - } - if (ADULT_CONTENT_LABELS.includes(cause.label.val as AdultSelfLabel)) { - if (hasAdultContentLabel) { - return false - } - hasAdultContentLabel = true - } - return true - }) - .slice(0, 2) - .map(cause => { - if (cause.type !== 'label') { - return - } + for (const cause of modui.blurs) { + if (cause.type !== 'label') continue + if (cause.source.type !== 'user') continue + if (ADULT_CONTENT_LABELS.includes(cause.label.val as AdultSelfLabel)) { + if (hasAdultContentLabel) continue + hasAdultContentLabel = true + } + selfBlurCauses.push(cause) + } + const selfBlurNames = selfBlurCauses.slice(0, 2).map(cause => { + if (cause.type !== 'label') { + return + } - const def = cause.labelDef || getDefinition(labelDefs, cause.label) - if (def.identifier === 'porn' || def.identifier === 'sexual') { - return l`Adult Content` - } - return getLabelStrings(i18n.locale, globalLabelStrings, def).name - }) + const def = cause.labelDef || getDefinition(labelDefs, cause.label) + if (def.identifier === 'porn' || def.identifier === 'sexual') { + return l`Adult Content` + } + return getLabelStrings(i18n.locale, globalLabelStrings, def).name + }) if (selfBlurNames.length === 0) { return desc.name diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx index e8e3613ddc..1c98b4bdfa 100644 --- a/src/state/session/index.tsx +++ b/src/state/session/index.tsx @@ -683,9 +683,11 @@ export function Provider({children}: React.PropsWithChildren<{}>) { const bundle = state.currentBundleState.bundle as unknown as SessionBundle | PublicSessionBundle - // @ts-expect-error window type is not declared, debug only - // eslint-disable-next-line react-hooks/immutability - if (__DEV__ && IS_WEB) window.bundle = bundle + useEffect(() => { + if (!__DEV__ || !IS_WEB) return + // @ts-expect-error window type is not declared, debug only + window.bundle = bundle + }, [bundle]) const currentBundleRef = useRef(bundle) /* diff --git a/src/view/com/pager/TabBar.tsx b/src/view/com/pager/TabBar.tsx index 0e259544ce..595c235f1d 100644 --- a/src/view/com/pager/TabBar.tsx +++ b/src/view/com/pager/TabBar.tsx @@ -332,7 +332,7 @@ export function TabBar({ syncScrollState.set('unsynced') }} onScroll={e => { - scrollX.value = Math.round(e.nativeEvent.contentOffset.x) + scrollX.set(Math.round(e.nativeEvent.contentOffset.x)) }}> {