-
Notifications
You must be signed in to change notification settings - Fork 1.4k
chore: react-compiler #6679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: react-compiler #6679
Conversation
WalkthroughProject-wide edits add a no-op 'use memo' string inside many React components and hooks, adjust ESLint to include react-hooks rules, and simplify several handlers by removing useCallback/useMemo. A few components switch implicit returns to block bodies. Minor refactors include dependency changes in a useMemo, an inline render change, a test assertion removal, and one internal component rename. Changes
Sequence Diagram(s)Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…se the transition and apply compiler to RoomsListView, SidebarView, Message and other components
|
Android Build Available Rocket.Chat Experimental 4.66.0.107543 Internal App Sharing: https://play.google.com/apps/test/RQVpXLytHNc/ahAO29uNTE49FEN4KmhIHpVjC16vpDt32BCO1DfZirpS9fCxhYe_pPwjA-1Lur7YVLmjej7cbN0-BMcA7mJPqSAZQ4 |
|
iOS Build Available Rocket.Chat Experimental 4.66.0.107544 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 14
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/containers/message/Message.tsx (1)
128-149: Fix thread reply accessibility labelWhen
props.tmidis falsy we now interpolate the entirepropsobject, so the screen reader announces “replying to [object Object]…”. Restore the original message text to keep the accessibility label meaningful.Apply this diff:
- if (props.isThreadReply) { - label = `replying to ${props.tmid ? `thread message ${props.msg}` : props}`; + if (props.isThreadReply) { + label = `replying to ${props.tmid ? `thread message ${props.msg}` : props.msg}`;
♻️ Duplicate comments (26)
app/containers/message/Components/RightIcons/MessageError.tsx (1)
13-13: Same directive verification needed (see Encrypted.tsx).This component follows the same pattern as Encrypted.tsx. The directive syntax and redundancy with
React.memo(line 11) need verification. Note that this component uses a custom comparison function (line 28), which may interact with compiler optimizations in unexpected ways.app/containers/message/Components/RightIcons/Pinned.tsx (1)
7-7: Directive syntax verification needed; no fallback memoization.Unlike other components in this directory,
Pinnedis not wrapped withReact.memo. If the'use memo'directive is invalid or unsupported, this component will have no memoization, potentially causing unnecessary re-renders.app/containers/message/Components/RightIcons/Translated.tsx (1)
8-8: Same directive verification needed (see Encrypted.tsx).app/containers/message/Components/RightIcons/ReadReceipt.tsx (1)
8-8: Same directive verification needed (see Encrypted.tsx).app/containers/message/Components/RightIcons/index.tsx (1)
38-51: Directive syntax verification needed; block body conversion required.The component was converted from an implicit return to a block body to accommodate the directive. While this conversion is necessary for placing directives, the
'use memo'syntax itself requires verification (see comments on Encrypted.tsx). LikePinned.tsx, this component is not wrapped withReact.memo, so if the directive is unsupported, memoization will be absent.app/containers/message/Components/RightIcons/Edited.tsx (1)
8-8: Same directive verification needed (see Encrypted.tsx).app/containers/message/CallButton.tsx (1)
14-16: Redundant memoization (duplicate concern).Similar to other components in this PR, both
React.memo()wrapper and'use memo'directive are present. Refer to the verification request in Item.tsx for a project-wide check.app/containers/MessageComposer/components/Autocomplete/AutocompletePreview.tsx (1)
11-12: Invalid directive: 'use memo' does not exist in React.This string literal is not a recognized React directive and has no functional effect. React Compiler is enabled via build configuration, not component-level directives.
Remove this non-functional code:
- 'use memo'; -app/containers/ActionSheet/Provider.tsx (1)
57-58: Invalid directive: 'use memo' does not exist in React.This non-functional string literal should be removed. React Compiler is configured at the build level, not with component directives.
- 'use memo'; -app/containers/MessageComposer/components/Autocomplete/AutocompleteEmoji.tsx (1)
9-10: Invalid directive: 'use memo' does not exist in React.Remove this non-functional directive.
- 'use memo'; -app/containers/message/Components/Attachments/CollapsibleQuote/index.tsx (3)
88-89: Invalid directive: 'use memo' does not exist in React.Remove this non-functional directive from the
AttTextcomponent.- 'use memo'; -
103-104: Invalid directive: 'use memo' does not exist in React.Remove this non-functional directive from the
Fieldscomponent.- 'use memo'; -
130-131: Invalid directive: 'use memo' does not exist in React.Remove this non-functional directive from the
CollapsibleQuotecomponent.- 'use memo'; -app/containers/MessageComposer/components/Autocomplete/styles.ts (1)
7-8: Invalid directive: 'use memo' does not exist in React.Remove this non-functional directive from the
useStylehook.- 'use memo'; -app/containers/message/Components/Attachments/Image/Container.tsx (1)
23-24: Same issue as MessageComposer.tsx.This string directive is a no-op and doesn't enable React Compiler. See the detailed comment in MessageComposer.tsx regarding proper React Compiler configuration.
app/containers/MessageComposer/components/Buttons/ActionsButton.tsx (1)
15-16: Same issue as MessageComposer.tsx.This string directive is a no-op and doesn't enable React Compiler. See the detailed comment in MessageComposer.tsx regarding proper React Compiler configuration.
app/views/RoomsListView/components/Header.tsx (1)
35-36: Same issue as MessageComposer.tsx.This string directive is a no-op and doesn't enable React Compiler. See the detailed comment in MessageComposer.tsx regarding proper React Compiler configuration.
app/containers/MessageComposer/components/MessageComposerContent.tsx (1)
27-28: Same issue as MessageComposer.tsx, plus redundancy with existingmemo().This string directive is a no-op and doesn't enable React Compiler. Additionally, this component is already wrapped with
memo()at line 25, making any compiler-based memoization redundant. See the detailed comment in MessageComposer.tsx regarding proper React Compiler configuration.app/containers/MessageComposer/components/SendThreadToChannel.tsx (1)
19-20: Same issue as MessageComposer.tsx.This string directive is a no-op and doesn't enable React Compiler. See the detailed comment in MessageComposer.tsx regarding proper React Compiler configuration.
app/containers/MessageComposer/components/Toolbar/EmojiKeyboard.tsx (1)
11-12: Same issue as MessageComposer.tsx.This string directive is a no-op and doesn't enable React Compiler. See the detailed comment in MessageComposer.tsx regarding proper React Compiler configuration.
app/containers/MessageComposer/components/Unfocused/Right.tsx (1)
11-12: Same issue as MessageComposer.tsx.This string directive is a no-op and doesn't enable React Compiler. See the detailed comment in MessageComposer.tsx regarding proper React Compiler configuration.
app/containers/MessageComposer/hooks/useAutoSaveDraft.ts (1)
9-10: React Compiler directive in custom hook.The
'use memo'directive is added to a custom hook. While the React Compiler may support optimizing hooks, ensure this is intentional and that the compiler is configured to process hooks as well as components.app/containers/MessageComposer/components/Autocomplete/AutocompleteUserRoom.tsx (1)
12-13: React Compiler directive requires active compilation.app/containers/message/MessageAvatar.tsx (1)
20-21: Potentially redundant with React.memo wrapper.Similar to other components in this PR, the
'use memo'directive is added to a component already wrapped inReact.memo()(line 19). Clarify whether both the directive and the HOC are necessary, or if one can be removed once the compiler is confirmed to be active.app/containers/message/Components/Attachments/Image/Image.tsx (1)
17-18: Potentially redundant with React.memo wrapper.app/containers/MessageComposer/components/Buttons/MicOrSendButton.tsx (1)
16-17: React Compiler directive requires active compilation.
🧹 Nitpick comments (10)
app/containers/UIKit/Actions.tsx (2)
14-18: Simplify by removing the nested fragment and redundant ternary.The nested fragment and ternary operator are unnecessary:
- The inner
<>...</>adds no value when already wrapped in an outer fragment- The ternary
renderedElements ? ... : nullis redundant becauserenderedElements?.map()returnsundefinedfor nullish values, which React doesn't renderApply this diff to simplify:
- <> - {renderedElements - ? renderedElements?.map(element => parser?.renderActions({ blockId, appId, ...element }, BlockContext.ACTION, parser)) - : null} - </> + {renderedElements?.map(element => parser?.renderActions({ blockId, appId, ...element }, BlockContext.ACTION, parser))}
15-17: Add a key prop to the mapped elements.Each element in the map should have a unique
keyprop to help React efficiently update the list and avoid potential rendering issues.If
elementhas a unique identifier (e.g.,element.idorelement.actionId), use it as the key:- {renderedElements - ? renderedElements?.map(element => parser?.renderActions({ blockId, appId, ...element }, BlockContext.ACTION, parser)) - : null} + {renderedElements?.map((element, index) => ( + <React.Fragment key={element.actionId || element.id || index}> + {parser?.renderActions({ blockId, appId, ...element }, BlockContext.ACTION, parser)} + </React.Fragment> + ))}Note: Prefer a stable unique identifier over
indexif available.app/containers/message/Time.tsx (1)
14-15: React Compiler annotation mode is enabled, so'use memo'will be applied.MessageTimeis a simple presentational component; the performance benefit is minimal—consider omitting the directive here unless adhering to a consistent opt-in pattern is preferred.app/containers/Header/components/HeaderButton/HeaderButtonItem.tsx (1)
56-57: Consider documenting the React Compiler directive.The
'use memo'directive opts this component into React Compiler optimization. Since this component is already wrapped withReact.memo()(line 44), consider adding a comment explaining how these two memoization strategies interact when the compiler is active.Add a brief comment above the directive:
}: IHeaderButtonItem): React.ReactElement => { + // React Compiler directive: auto-optimize re-renders and memoization 'use memo';app/containers/ActionSheet/Handle.tsx (1)
9-10: Potentially redundant with React.memo wrapper.The
'use memo'directive is added to a component already wrapped inReact.memo()(line 8). If the React Compiler is not actively compiling this code, theReact.memowrapper provides the memoization. If the compiler is active, verify whether both are needed or if the directive alone is sufficient.app/views/RoomView/LeftButtons.tsx (1)
40-40: Avoid recreating the onPress closure each renderCreating a new arrow per render can defeat memoization downstream (e.g., Avatar wrapped in React.memo).
Option A (simplest): pass the handler directly and remove the extra closure.
- const onPress = () => goRoomActionsView();And where used (line 58):
- return <Avatar rid={rid} text={title} size={30} type={t} style={styles.avatar} onPress={onPress} />; + return <Avatar rid={rid} text={title} size={30} type={t} style={styles.avatar} onPress={goRoomActionsView} />;Option B: if you prefer keeping the wrapper, memoize it (or add 'use memo' at the top of the component).
- const onPress = () => goRoomActionsView(); + // const onPress = useCallback(() => goRoomActionsView(), [goRoomActionsView]); + // or: add `'use memo';` as the first statement in this component bodyapp/containers/UIKit/Select.tsx (1)
63-63: Stabilizeitemsto avoid recomputingplaceholderObjectevery renderDepending on
itemsis semantically correct, but sinceitemsis rebuilt each render, the memo will always invalidate. Memoizeitemsfromoptionsso[items, placeholder]is effective.Apply outside the selected range (around line 50):
- const items = options.map(option => ({ label: textParser([option.text]), value: option.value })); + const items = useMemo( + () => options.map(option => ({ label: textParser([option.text]), value: option.value })), + [options] +);Keep your current dependency array:
[items, placeholder]app/containers/RoomHeader/RoomHeader.tsx (1)
193-201: Simplify handler and tighten typeNo need to wrap onPress. Pass it directly and type it as () => void to avoid the extra closure.
- const handleOnPress = () => onPress(); ... - <TouchableOpacity testID='room-header' onPress={handleOnPress} disabled={disabled} hitSlop={HIT_SLOP}> + <TouchableOpacity testID='room-header' onPress={onPress} disabled={disabled} hitSlop={HIT_SLOP}>Optionally update the prop type:
interface IRoomHeader { // ... - onPress: Function; + onPress: () => void; }app/stacks/InsideStack.tsx (1)
97-98: Navigator-level 'use memo' directivesSafe as directives; they’re inert without the compiler. Benefit here is minimal since these components have no volatile props, but harmless to keep for consistency.
Please run the compiler verification script (Babel/Metro) shared earlier to ensure these directives are effective.
Also applies to: 164-165, 183-184, 212-213, 226-227, 241-242, 269-270, 288-289, 303-304, 317-318
app/views/CreateChannelView/RoomSettings/index.tsx (1)
42-49: Gate closures with React Compiler or memoize handlers
babel-plugin-react-compiler is enabled (annotation mode), so addexport const RoomSettings = (…) => { 'use memo'; // … }to stabilize onValueChangeType/onValueChangeReadOnly/onValueChangeEncrypted, or wrap each in useCallback (e.g.
[encrypted, setValue]for onValueChangeType). Also verify that toggling public/private correctly resets encryption per product spec.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (2)
app/containers/MessageComposer/__snapshots__/MessageComposer.test.tsx.snapis excluded by!**/*.snapyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (107)
.eslintrc.js(2 hunks)app/containers/ActionSheet/BottomSheetContent.tsx(1 hunks)app/containers/ActionSheet/Handle.tsx(1 hunks)app/containers/ActionSheet/Item.tsx(1 hunks)app/containers/ActionSheet/Provider.tsx(1 hunks)app/containers/Header/components/HeaderBackButton.tsx(1 hunks)app/containers/Header/components/HeaderButton/HeaderButtonItem.tsx(1 hunks)app/containers/Header/components/HeaderContainer/index.tsx(1 hunks)app/containers/Header/components/HeaderTitle/index.tsx(1 hunks)app/containers/Header/index.tsx(1 hunks)app/containers/List/ListContainer.tsx(1 hunks)app/containers/List/ListHeader.tsx(1 hunks)app/containers/List/ListIcon.tsx(1 hunks)app/containers/List/ListInfo.tsx(1 hunks)app/containers/List/ListItem.tsx(4 hunks)app/containers/List/ListSection.tsx(1 hunks)app/containers/List/ListSeparator.tsx(1 hunks)app/containers/MessageComposer/MessageComposer.test.tsx(1 hunks)app/containers/MessageComposer/MessageComposer.tsx(1 hunks)app/containers/MessageComposer/MessageComposerContainer.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/Autocomplete.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/AutocompleteCannedResponse.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/AutocompleteEmoji.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/AutocompleteItem.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/AutocompleteItemLoading.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/AutocompletePreview.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/AutocompleteSlashCommand.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/AutocompleteUserRoom.tsx(1 hunks)app/containers/MessageComposer/components/Autocomplete/styles.ts(1 hunks)app/containers/MessageComposer/components/Buttons/ActionsButton.tsx(1 hunks)app/containers/MessageComposer/components/Buttons/BaseButton.tsx(1 hunks)app/containers/MessageComposer/components/Buttons/MicOrSendButton.tsx(1 hunks)app/containers/MessageComposer/components/CancelEdit.tsx(1 hunks)app/containers/MessageComposer/components/EmojiSearchbar.tsx(1 hunks)app/containers/MessageComposer/components/MessageComposerContent.tsx(1 hunks)app/containers/MessageComposer/components/Quotes/Quote.tsx(1 hunks)app/containers/MessageComposer/components/Quotes/Quotes.tsx(1 hunks)app/containers/MessageComposer/components/RecordAudio/ReviewButton.tsx(1 hunks)app/containers/MessageComposer/components/SendThreadToChannel.tsx(1 hunks)app/containers/MessageComposer/components/Toolbar/Container.tsx(1 hunks)app/containers/MessageComposer/components/Toolbar/Default.tsx(1 hunks)app/containers/MessageComposer/components/Toolbar/EmojiKeyboard.tsx(1 hunks)app/containers/MessageComposer/components/Toolbar/Markdown.tsx(1 hunks)app/containers/MessageComposer/components/Toolbar/Toolbar.tsx(1 hunks)app/containers/MessageComposer/components/Unfocused/Left.tsx(1 hunks)app/containers/MessageComposer/components/Unfocused/Right.tsx(1 hunks)app/containers/MessageComposer/context.tsx(1 hunks)app/containers/MessageComposer/hooks/useAutoSaveDraft.ts(1 hunks)app/containers/MessageComposer/hooks/useCanUploadFile.ts(1 hunks)app/containers/MessageComposer/hooks/useChooseMedia.ts(1 hunks)app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx(3 hunks)app/containers/MessageComposer/hooks/useIOSBackSwipeHandler.ts(1 hunks)app/containers/MessageComposer/hooks/useMessage.ts(1 hunks)app/containers/RoomHeader/RoomHeader.tsx(2 hunks)app/containers/RoomItem/RoomItem.tsx(1 hunks)app/containers/SearchBox/index.tsx(2 hunks)app/containers/UIKit/Actions.tsx(1 hunks)app/containers/UIKit/Select.tsx(1 hunks)app/containers/message/Blocks.ts(1 hunks)app/containers/message/Broadcast.tsx(1 hunks)app/containers/message/CallButton.tsx(1 hunks)app/containers/message/Components/Attachments/AttachedActions.tsx(1 hunks)app/containers/message/Components/Attachments/Attachments.tsx(1 hunks)app/containers/message/Components/Attachments/Audio.tsx(1 hunks)app/containers/message/Components/Attachments/CollapsibleQuote/index.tsx(3 hunks)app/containers/message/Components/Attachments/Image/Button.tsx(1 hunks)app/containers/message/Components/Attachments/Image/Container.tsx(1 hunks)app/containers/message/Components/Attachments/Image/Image.tsx(1 hunks)app/containers/message/Components/Attachments/Image/ImageBadge.tsx(1 hunks)app/containers/message/Components/Attachments/Quote.tsx(1 hunks)app/containers/message/Components/Attachments/Reply.tsx(5 hunks)app/containers/message/Components/Attachments/Video.tsx(1 hunks)app/containers/message/Components/OverlayComponent/index.tsx(1 hunks)app/containers/message/Components/RightIcons/Edited.tsx(1 hunks)app/containers/message/Components/RightIcons/Encrypted.tsx(1 hunks)app/containers/message/Components/RightIcons/MessageError.tsx(1 hunks)app/containers/message/Components/RightIcons/Pinned.tsx(1 hunks)app/containers/message/Components/RightIcons/ReadReceipt.tsx(1 hunks)app/containers/message/Components/RightIcons/Translated.tsx(1 hunks)app/containers/message/Components/RightIcons/index.tsx(1 hunks)app/containers/message/Components/WidthAwareView.tsx(1 hunks)app/containers/message/Content.tsx(1 hunks)app/containers/message/Discussion.tsx(1 hunks)app/containers/message/Emoji.tsx(1 hunks)app/containers/message/Message.tsx(5 hunks)app/containers/message/MessageAvatar.tsx(1 hunks)app/containers/message/Preview.tsx(1 hunks)app/containers/message/Reactions.tsx(3 hunks)app/containers/message/RepliedThread.tsx(1 hunks)app/containers/message/Thread.tsx(1 hunks)app/containers/message/Time.tsx(1 hunks)app/containers/message/Touchable.tsx(1 hunks)app/containers/message/Urls.tsx(3 hunks)app/containers/message/User.tsx(1 hunks)app/containers/message/hooks/useFile.tsx(1 hunks)app/containers/message/hooks/useMediaAutoDownload.tsx(1 hunks)app/stacks/InsideStack.tsx(10 hunks)app/stacks/MasterDetailStack/ModalContainer.tsx(1 hunks)app/stacks/MasterDetailStack/index.tsx(3 hunks)app/stacks/OutsideStack.tsx(2 hunks)app/stacks/ShareExtensionStack.tsx(1 hunks)app/views/CreateChannelView/RoomSettings/index.tsx(2 hunks)app/views/PushTroubleshootView/index.tsx(1 hunks)app/views/RoomView/LeftButtons.tsx(2 hunks)app/views/RoomsListView/components/Container.tsx(1 hunks)app/views/RoomsListView/components/Header.tsx(1 hunks)app/views/RoomsListView/components/ListHeader.tsx(1 hunks)
⛔ Files not processed due to max files limit (19)
- app/views/RoomsListView/components/SectionHeader.tsx
- app/views/RoomsListView/components/ServersList.tsx
- app/views/RoomsListView/components/TabletHeader.tsx
- app/views/RoomsListView/contexts/RoomsSearchProvider.tsx
- app/views/RoomsListView/hooks/useGetItemLayout.ts
- app/views/RoomsListView/hooks/useHeader.tsx
- app/views/RoomsListView/hooks/useRefresh.ts
- app/views/RoomsListView/hooks/useSearch.ts
- app/views/RoomsListView/hooks/useSubscriptions.ts
- app/views/RoomsListView/index.tsx
- app/views/SettingsView/index.tsx
- app/views/SidebarView/components/Admin.tsx
- app/views/SidebarView/components/CustomStatus.tsx
- app/views/SidebarView/components/Profile.tsx
- app/views/SidebarView/components/Stacks.tsx
- app/views/SidebarView/components/SupportedVersionsWarnItem.tsx
- app/views/SidebarView/index.tsx
- babel.config.js
- package.json
🧰 Additional context used
🧬 Code graph analysis (5)
app/stacks/OutsideStack.tsx (1)
app/stacks/types.ts (1)
OutsideModalParamList(324-331)
app/containers/MessageComposer/MessageComposerContainer.tsx (2)
app/containers/MessageComposer/context.tsx (1)
MessageComposerProvider(82-128)app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx (1)
EmojiKeyboardProvider(22-33)
app/views/CreateChannelView/RoomSettings/index.tsx (1)
app/lib/methods/helpers/log/index.ts (1)
logEvent(35-42)
app/stacks/MasterDetailStack/index.tsx (3)
app/lib/methods/helpers/navigation/index.ts (1)
drawerStyle(13-15)app/stacks/MasterDetailStack/types.ts (1)
ModalStackParamList(30-210)app/stacks/stackType.ts (1)
TNavigation(4-20)
app/containers/List/ListSection.tsx (1)
app/containers/List/List.stories.tsx (1)
Header(51-56)
🔇 Additional comments (50)
app/containers/RoomItem/RoomItem.tsx (1)
58-58: Directive placement looks good.
'use memo';is correctly positioned at the top of the component body for React Compiler adoption. 👍app/containers/message/Broadcast.tsx (1)
15-17: Directive placement looks good.The
'use memo'directive is correctly positioned at the top of the component body and doesn’t alter runtime behavior. 👍app/containers/message/Components/Attachments/Quote.tsx (1)
27-28: Directive placement looks correctThe
'use memo';directive is positioned as the first statement in the component body, so it should be properly picked up when the React Compiler runs. Nicely done.app/containers/MessageComposer/components/Toolbar/Toolbar.tsx (1)
14-14: Directive placement looks good.
'use memo';is correctly placed at the top of the component and does not affect existing logic. Good to go.app/containers/message/Components/Attachments/Audio.tsx (1)
21-22: React Compiler directive applied and configuredBabel config includes
babel-plugin-react-compilerin annotation mode and package.json lists the dependency, so the'use memo'directive will be processed as intended.app/stacks/ShareExtensionStack.tsx (1)
12-13: No action needed for 'use memo'. Thebabel-plugin-react-compileris already configured inbabel.config.jsand declared inpackage.json, so the directive will be applied as intended.app/containers/message/RepliedThread.tsx (1)
13-14: Directive placement looks good.The
'use memo'opt-in is correctly placed at the top of the component, matching the React Compiler guidelines.app/containers/message/hooks/useFile.tsx (1)
8-9: 'use memo' directive placement and configuration are correct. Thebabel-plugin-react-compileris enabled in babel.config.js (annotation mode) and declared in package.json. No further action required.app/containers/message/Components/Attachments/Video.tsx (1)
84-85: React Compiler directive looks goodAdding
'use memo';as the first statement cleanly opts this component into the compiler without affecting runtime behavior.app/containers/MessageComposer/components/Toolbar/Markdown.tsx (1)
10-10: Directive placement looks correct.
'use memo'is the first statement in the component body, so the compiler can wrap this toolbar without altering runtime behavior.app/containers/MessageComposer/components/RecordAudio/ReviewButton.tsx (1)
11-11: Opt-in directive acknowledged.The hook and theming logic stay untouched while opting the button into the compiler—looks good.
app/containers/MessageComposer/components/Buttons/BaseButton.tsx (1)
24-24: Ready for compiler auto-memoization.With
'use memo'leading the body, the compiler can memoize this reusable button without affecting its dimension-driven updates.app/containers/Header/index.tsx (1)
15-15: Header marked for compiler safely.The directive sits first, and the component’s state/prop usage is still explicit, so the compiler opt-in won’t mask updates.
app/containers/MessageComposer/hooks/useCanUploadFile.ts (1)
7-7: Hook opt-in looks good.
'use memo'leads the hook, and its derived boolean remains deterministic, so compiler memoization is safe here.app/containers/MessageComposer/hooks/useIOSBackSwipeHandler.ts (1)
8-8: Directive applied without side effects.The hook still sets up navigation listeners exactly as before while opting into the compiler pipeline.
app/containers/MessageComposer/components/Unfocused/Left.tsx (1)
11-12: "use memo" is the opt-in annotation for babel-plugin-react-compiler (compilationMode: "annotation"); it’s recognized at build time and has no runtime effect. Consider adding a brief inline comment or README entry to explain its purpose.app/containers/message/Components/WidthAwareView.tsx (1)
13-14: LGTM!The
'use memo'directive is correctly placed for React Compiler optimization. Since this component manages state and re-renders on layout changes, compiler optimization should improve performance.app/stacks/MasterDetailStack/ModalContainer.tsx (1)
33-34: LGTM!Appropriate use of the
'use memo'directive. The component uses multiple hooks and recalculates modal height on dimension changes, making it a good candidate for React Compiler optimization.app/containers/MessageComposer/components/Autocomplete/AutocompleteCannedResponse.tsx (1)
12-13: LGTM!The directive is correctly placed for this straightforward rendering component.
app/views/PushTroubleshootView/index.tsx (1)
23-27: LGTM - Correctly fixes dependency array.Adding
dispatchto the dependency array follows React Hooks best practices. While Redux'sdispatchis stable and won't actually cause re-creation of the callback, explicitly declaring it satisfies theexhaustive-depsrule and makes the code more maintainable.app/containers/MessageComposer/components/Autocomplete/AutocompleteItemLoading.tsx (1)
8-9: LGTM!The directive is appropriately placed for this component with conditional rendering logic.
app/containers/ActionSheet/Item.tsx (1)
18-20: Remove 'use memo' directive
React does not recognize'use memo'as a compiler directive; theReact.memo()wrapper remains necessary.Likely an incorrect or invalid review comment.
app/containers/message/Content.tsx (1)
16-19: No action required: React Compiler preserves custom memo comparators
The compiler’s preserve-manual-memoization rule retains React.memo calls with custom arePropsEqual comparators, even when using theuse memodirective. [1][2].eslintrc.js (2)
17-17: LGTM: Added React Hooks ESLint preset.Adding
plugin:react-hooks/recommendedis appropriate for enforcing Hooks best practices.
39-41: Additional React Hooks rules are valid:react-hooks/set-state-in-effect,react-hooks/immutability, andreact-hooks/refsare supported opt-in rules in eslint-plugin-react-hooks v6+; no removal required.app/containers/MessageComposer/MessageComposer.tsx (1)
34-35:'use memo'directives are recognized with annotation mode.Babel config (
babel.config.js) usesbabel-plugin-react-compilerwithcompilationMode: 'annotation', so the'use memo'string at the top of the component correctly opts it into compilation. No changes needed.Likely an incorrect or invalid review comment.
app/containers/message/Components/Attachments/Attachments.tsx (1)
20-21: React Compiler directive applied consistently.The
'use memo'directive is correctly positioned. Note that this component also usesReact.memo()with a customdequalcomparator (lines 18-90). The compiler may optimize the component differently, but the explicit comparator ensures attachment deep equality checks remain intact.app/containers/message/hooks/useMediaAutoDownload.tsx (1)
60-61: LGTM: React Compiler directive in custom hook.The
'use memo'directive is appropriately placed at the start of this custom hook. The compiler can optimize the hook's internal state management and callbacks, which is beneficial given the hook's complexity (download state, caching, side effects).app/containers/MessageComposer/components/Toolbar/Default.tsx (1)
12-13: LGTM!The React Compiler directive is correctly positioned.
app/containers/message/Preview.tsx (1)
9-10: LGTM!The React Compiler directive is correctly positioned.
app/containers/MessageComposer/components/Autocomplete/Autocomplete.tsx (1)
23-24: LGTM!The React Compiler directive is correctly positioned for this autocomplete component.
app/containers/ActionSheet/BottomSheetContent.tsx (1)
23-24: LGTM: React Compiler directive with React.memo.The directive is correctly positioned. This component also uses
React.memo()(line 22), which works in conjunction with the compiler optimization.app/containers/MessageComposer/context.tsx (1)
83-84: React Compiler plugin is correctly configured
Babel config includesbabel-plugin-react-compiler(compilationMode: 'annotation') and Metro picks it up, so'use memo'directives are processed as intended.app/containers/message/Thread.tsx (1)
13-13: LGTM!The directive is correctly placed inside the memoized component body.
app/containers/message/User.tsx (1)
83-83: LGTM!The directive is correctly positioned for React Compiler opt-in.
app/containers/Header/components/HeaderTitle/index.tsx (1)
13-13: LGTM!The directive is correctly placed.
app/containers/MessageComposer/components/Toolbar/Container.tsx (1)
4-16: LGTM!The conversion from implicit return to explicit block body is clean, and the
'use memo'directive is correctly positioned.app/containers/MessageComposer/hooks/useChooseMedia.ts (1)
25-25: LGTM!The directive is correctly placed at the top of the custom hook body.
app/containers/message/Reactions.tsx (1)
32-32: LGTM!All three components (
AddReaction,Reaction, andReactions) have the directive correctly placed for React Compiler opt-in.Also applies to: 53-53, 86-86
app/containers/Header/components/HeaderBackButton.tsx (1)
23-23: LGTM!The directive is correctly positioned for React Compiler opt-in.
app/containers/MessageComposer/components/Autocomplete/AutocompleteSlashCommand.tsx (1)
9-9: React Compiler directive added correctly and plugin configuration verified.app/containers/SearchBox/index.tsx (1)
1-1: Verify callback stability for FormTextInput or re-add useCallback.Removing
useCallbackfrominternalOnChangeTextrecreates the function each render. EnsureFormTextInputis wrapped inReact.memo(or equivalent) or that the React Compiler is actively optimizing this code; otherwise reintroduceuseCallbackto maintain stable callback references and avoid unnecessary re-renders.app/containers/MessageComposer/components/Autocomplete/AutocompleteItem.tsx (1)
74-75: Verified React Compiler setup: babel-plugin-react-compiler is included in package.json and babel.config.js (annotation mode), so the ‘use memo’ directive will be processed.app/containers/message/Touchable.tsx (1)
7-7: LGTMDirective is correctly placed; no functional changes.
app/containers/MessageComposer/hooks/useEmojiKeyboard.tsx (1)
23-24: LGTMDirectives are correctly placed at the top of each function; runtime behavior unchanged.
Also applies to: 39-40, 71-72
app/containers/Header/components/HeaderContainer/index.tsx (1)
16-16: 'use memo' placement is correct; verify React Compiler plugin configuration
Ensurebabel-plugin-react-compileror@react/compileris listed in package.json and applied in your Babel/Metro config; otherwise'use memo'directives are no-ops.app/containers/message/Components/Attachments/Reply.tsx (1)
104-105: 'use memo' directives: OK, but ensure compiler is enabled and ESLint allows directivesThese prologue directives are no-ops unless the React Compiler transform runs. Please verify Babel/Metro setup; otherwise they add no benefit. Also ensure ESLint no-unused-expressions treats these as directives (usually fine at top of function bodies).
Reuse the compiler verification script from my other comment to confirm setup.
Also applies to: 131-132, 165-166, 189-190, 214-215
app/containers/List/ListContainer.tsx (1)
16-28: Directive addition looks fineThe block body with 'use memo' preserves behavior. No functional changes.
Confirm React Compiler configuration so this directive has effect (see repo-wide script in my earlier comment).
app/stacks/OutsideStack.tsx (2)
20-20: Component rename is clear and improves code organization.The rename from
_OutsideStacktoOutsideStackComponentmakes the internal component name more explicit and aligns with common naming conventions.
20-22: Drop the'use memo'directive complaint
"use memo"is a valid React Compiler annotation when placed as the first statement to opt a component into compilation optimizations. No changes required.Likely an incorrect or invalid review comment.
| 'use memo'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive in memoized component.
ListHeader is already wrapped with React.memo() on line 27. The 'use memo'; directive is both invalid and redundant.
🤖 Prompt for AI Agents
In app/containers/List/ListHeader.tsx around lines 28-29, the string directive
'use memo'; is invalid and redundant because the component is already wrapped
with React.memo() on line 27; remove the 'use memo'; line and keep the existing
React.memo wrapper (ensure no other stray directive strings remain).
| 'use memo'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive in memoized component.
ListInfo is already wrapped with React.memo() on line 27. The 'use memo'; directive is both invalid and redundant.
🤖 Prompt for AI Agents
In app/containers/List/ListInfo.tsx around lines 28-29 the file contains an
invalid and redundant directive "'use memo';" even though the component is
already wrapped with React.memo on line 27; remove the "'use memo';" line
entirely and keep the existing React.memo wrapper as the memoization mechanism
so the file no longer contains the invalid directive.
| 'use memo'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive in memoized component.
ListSeparator is already wrapped with React.memo() on line 17. The 'use memo'; directive is:
- Not a valid React directive
- Redundant with the existing React.memo() wrapper
🤖 Prompt for AI Agents
In app/containers/List/ListSeparator.tsx around lines 18–19, the file contains
an invalid and redundant "'use memo';" directive even though the component is
already wrapped with React.memo() on line 17; remove the "'use memo';" line
entirely (or replace it with a valid directive like 'use client' only if needed
for React/Next) so the file contains no invalid custom directive and relies on
the existing React.memo wrapper.
| import { E2E_MESSAGE_TYPE } from '../../../../lib/constants/keys'; | ||
|
|
||
| const Encrypted = React.memo(({ type }: { type: string }) => { | ||
| 'use memo'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Verify the React Compiler directive syntax.
The 'use memo' directive syntax is non-standard and needs verification. React Compiler (experimental) may use different opt-in mechanisms or no explicit directive. Additionally, combining this directive with the existing React.memo wrapper (line 10) may be redundant if the compiler handles memoization automatically.
Please verify the following:
-
Check React Compiler documentation for the correct directive syntax:
-
Verify whether manual
React.memowrappers are needed when using React Compiler directives:
🌐 Web query:
What is the correct directive syntax for React Compiler to opt-in components? Is 'use memo' a valid directive?
💡 Result:
Yes — the React Compiler uses the directive "use memo" (exactly, in quotes) to opt a function/component into compiler optimizations. Put it as the very first statement in the function body (single or double quotes, not backticks). Example:
function MyComponent() {
"use memo";
// ...
}
Notes: it's required in compilationMode: "annotation"; in infer/all modes it's usually unnecessary. [1][2]
Sources:
[1] React docs — "use memo" directive.
[2] React docs — directives / "use client" (general placement/quote rules).
🌐 Web query:
Does React Compiler require manual React.memo wrappers or does it handle memoization automatically when opted-in?
💡 Result:
Short answer: The React Compiler handles memoization automatically when you enable/opt-in to it — you don't need to wrap components in React.memo. It will insert granular memoization (and preserve/manual memoization when present), but will bail out for specific components/hooks if it detects rule violations or mismatches so it stays safe. [1][2]
Sources:
- React Compiler introduction (automatic memoization). [1]
- Incremental adoption / opt-in and preservation behavior. [2]
Remove redundant React.memo wrapper
The "use memo" directive in Encrypted.tsx opts the component into compiler memoization, so the manual React.memo wrapper (around the component definition) can be removed.
🤖 Prompt for AI Agents
In app/containers/message/Components/RightIcons/Encrypted.tsx around line 11,
the file uses the "use memo" directive which enables compiler-level memoization,
so remove the redundant manual React.memo wrapper around the component
definition/export; keep the "use memo" directive and export the component
directly (as a plain function or const) instead of wrapping it in React.memo,
and ensure any prop typing remains unchanged.
| 'use memo'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive: 'use memo' does not exist in React.
React Compiler does not use a 'use memo' directive. Valid React directives are only 'use client' and 'use server' (for React Server Components and Server Actions). React Compiler automatically optimizes components when enabled via Babel/Webpack configuration—no manual directives are needed or supported.
This string literal has no effect and creates misleading code.
To enable React Compiler, configure it in your build tooling instead:
- 'use memo';
-Then add to babel.config.js or similar:
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
// compiler options
}]
]
};🤖 Prompt for AI Agents
In app/containers/message/Emoji.tsx around lines 10-11, the file contains an
invalid directive "'use memo'" which is not a recognized React directive and is
misleading; remove this string literal line from the file so only valid
directives (e.g., 'use client' or 'use server' when needed) remain, and if you
intended to enable compiler optimizations configure the React Compiler via your
build tooling (babel/webpack) rather than using a source-level directive.
| const ChatsStackNavigator = React.memo(() => { | ||
| 'use memo'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive in memoized component.
ChatsStackNavigator is already wrapped with React.memo() on line 82. Adding 'use memo'; is:
- Not a valid React directive
- Redundant even if it were valid, since the component is already memoized
🤖 Prompt for AI Agents
In app/stacks/MasterDetailStack/index.tsx around lines 82 to 84, the string
literal "'use memo';" inside the ChatsStackNavigator component is invalid and
redundant; remove that line so the component is only memoized via React.memo()
and contains no unsupported directive strings, ensuring the function body
contains only valid JavaScript/JSX.
| const DrawerNavigator = React.memo(() => { | ||
| 'use memo'; | ||
|
|
||
| return ( | ||
| <Drawer.Navigator | ||
| screenOptions={{ drawerType: 'permanent', headerShown: false, drawerStyle: { ...drawerStyle } }} | ||
| drawerContent={() => <RoomsListView />}> | ||
| <Drawer.Screen name='ChatsStackNavigator' component={ChatsStackNavigator} /> | ||
| </Drawer.Navigator> | ||
| ); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive and redundant with React.memo.
The conversion to a block body with explicit return is fine as a style change. However, the 'use memo'; directive is invalid (see previous comments) and redundant since DrawerNavigator is already wrapped with React.memo().
🤖 Prompt for AI Agents
In app/stacks/MasterDetailStack/index.tsx around lines 96 to 106, the function
body contains an invalid and redundant directive "'use memo';" — remove that
line so the component relies solely on React.memo wrapping; keep the block-body
return as-is (or convert to implicit return if you prefer) but do not
reintroduce any nonstandard directive.
| const ModalStackNavigator = React.memo(({ navigation }: INavigation) => { | ||
| 'use memo'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive in already-memoized component.
ModalStackNavigator is wrapped with React.memo() on line 113, making the 'use memo'; directive both invalid and redundant.
🤖 Prompt for AI Agents
In app/stacks/MasterDetailStack/index.tsx around lines 113 to 114, the string
directive 'use memo'; inside the already memoized ModalStackNavigator is invalid
and redundant; remove the 'use memo'; line from the component so the memo
wrapper is the sole mechanism for memoization and ensure no other stray
directive strings remain in that function.
| const InsideStackNavigator = React.memo(() => { | ||
| 'use memo'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive in already-memoized component.
InsideStackNavigator is wrapped with React.memo() on line 212, making the 'use memo'; directive both invalid and redundant.
🤖 Prompt for AI Agents
In app/stacks/MasterDetailStack/index.tsx around lines 212 to 213, the literal
directive "'use memo';" inside the already-wrapped React.memo component is
invalid and redundant; remove that string directive from the component body so
the component remains memoized via React.memo without the invalid directive, and
run lint/type checks to confirm no stray directive remains (if you intended a
framework directive like "use client" replace it with the correct one).
| const OutsideStackModal = () => { | ||
| 'use memo'; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid directive: same 'use memo' issue.
The 'use memo'; directive in OutsideStackModal has the same problem as noted above—it's not a recognized React directive and serves no purpose.
🤖 Prompt for AI Agents
In app/stacks/OutsideStack.tsx around lines 50 to 52, the string directive 'use
memo' inside the OutsideStackModal component is invalid and should be removed;
delete that line and, if the intent was to memoize the component, wrap the
component export with React.memo (or export default
React.memo(OutsideStackModal)) or apply useMemo/useCallback inside the component
where appropriate to memoize values/handlers.
Co-authored-by: Rohit3523 <[email protected]> Co-authored-by: Diego Mello <[email protected]>
Proposed changes
Enables react-compiler with incremental adoption.
Applied on a few key components only for now:
Issue(s)
https://rocketchat.atlassian.net/browse/NATIVE-1060
How to test or reproduce
Screenshots
Types of changes
Checklist
Further comments
Summary by CodeRabbit
No new features or UI changes included in this release.