Skip to content

fix: support React.memo, forwardRef, and class components in all component props#2115

Open
naqvitalha wants to merge 1 commit intomainfrom
fix/support-memo-forwardref-exotic-components
Open

fix: support React.memo, forwardRef, and class components in all component props#2115
naqvitalha wants to merge 1 commit intomainfrom
fix/support-memo-forwardref-exotic-components

Conversation

@naqvitalha
Copy link
Collaborator

Summary

  • getValidComponent only checked typeof component === "function", silently dropping React.memo and React.forwardRef wrapped components (which are objects, not functions). This caused ListEmptyComponent, ListHeaderComponent, ListFooterComponent, and backdropComponent to render nothing when passed a memoized component.
  • renderScrollComponent called class components as plain functions via the same typeof === "function" branch, which would throw at runtime since classes require new / React.createElement.
  • All component prop types (CellRendererComponent, ItemSeparatorComponent, renderScrollComponent, etc.) only accepted React.ComponentType, rejecting memo/forwardRef at the TypeScript level.

Changes

File What changed
componentUtils.ts Broadened getValidComponent to handle all non-null component types; added isComponentClass utility
useSecondaryProps.tsx Use isComponentClass to avoid calling class scroll components as plain functions
FlashListProps.ts Added React.ExoticComponent to all 7 component prop types
componentUtils.test.tsx 12 new tests for getValidComponent and isComponentClass

Test plan

  • yarn build passes
  • yarn type-check passes
  • yarn lint passes
  • yarn test passes (177 tests, 14 suites)
  • Verified on iOS simulator — memoized ListEmptyComponent renders correctly

Fixes #1983

@naqvitalha naqvitalha force-pushed the fix/support-memo-forwardref-exotic-components branch from c64981d to 12653d1 Compare February 27, 2026 00:30
…onent props

`getValidComponent` only checked `typeof component === "function"`, which
excluded `React.memo` and `React.forwardRef` (both return objects). This
caused `ListEmptyComponent`, `ListHeaderComponent`, `ListFooterComponent`,
and `backdropComponent` to silently render nothing when passed a memoized
component.

Additionally, `renderScrollComponent` called class components as plain
functions (via the `typeof === "function"` branch), which would throw at
runtime since classes require instantiation.

Changes:
- Broaden `getValidComponent` to handle all non-null component types
- Add `isComponentClass` utility to distinguish class components from
  render functions in the scroll component logic
- Add `React.ExoticComponent` to the TypeScript types for all component
  props (ListEmptyComponent, ListHeaderComponent, ListFooterComponent,
  CellRendererComponent, ItemSeparatorComponent, renderScrollComponent,
  backdropComponent)

Fixes #1983
@naqvitalha naqvitalha force-pushed the fix/support-memo-forwardref-exotic-components branch from 12653d1 to 601b743 Compare February 27, 2026 00:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memoized component not rendered in ListEmptyComponent

1 participant