legend-list

A 100% JavaScript, drop-in replacement for FlatList and FlashList with better performance on dynamically sized items and no native dependencies.

Library
npm
v3.3.10
3,346stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
84/100Excellent
Development Activity96
Maintenance100
Community56
Maturity44
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture85
Code Quality78
Innovation85
Learning Curve55

Legend List is a high-performance list component for React Native and React, written purely in TypeScript with no native modules to link. It targets the same use case as FlatList and FlashList but is built from the ground up to handle items with varying, dynamically computed heights without the jank or scroll jumps those alternatives run into.

Beyond raw performance, it adds features aimed at real product needs: bidirectional infinite scrolling without flashes, chat-style layouts that pin to the bottom without inverting the list, optional item recycling for maximum throughput, and separate entrypoints for React DOM and React Native so the same component works across web and native.

What You Get

  • A LegendList component API-compatible with FlatList/FlashList (data, renderItem, keyExtractor, ListHeaderComponent, and more)
  • Optional item recycling, bidirectional infinite scroll, and chat-style bottom-alignment without list inversion
  • Dedicated subpath entrypoints for React DOM, React Native, Reanimated, keyboard-aware scrolling, and section lists
  • An imperative ref API (scrollToIndex, scrollToOffset, scrollToEnd) for programmatic control
  • Zero native dependencies — 100% JavaScript/TypeScript, so there’s no native linking or pod install step

Common Use Cases

  • Chat and messaging interfaces that need bottom-pinned, non-inverted scrolling
  • Social or content feeds with variable-height cards (text, images, video)
  • Migrating away from FlatList’s performance ceiling or FlashList’s native dependency
  • Cross-platform apps that share one virtualized list implementation across web and native

Under The Hood

Architecture The public LegendList component (src/components/LegendList.tsx) wraps a StateProvider and delegates virtualization, scroll, and layout orchestration to a large set of single-purpose modules under src/core (calculateItemsInView, updateScroll, scrollToIndex, viewability, bootstrapInitialScroll, doMaintainScrollAtEnd) that all operate on a shared ctx object rather than component props or React state. That shared state lives in src/state/state.tsx, a small Legend State-inspired store built on useSyncExternalStore with peek$/set$/listen$ primitives, letting scroll position, container sizes, and viewability update without forcing a full React re-render of the list. Rendering and recycling are handled separately in src/components/Container*.tsx and src/utils/containerPool.ts, which pool and reuse mounted item containers when recycleItems is enabled. Platform divergence (React DOM vs React Native, old vs new architecture) is resolved through .native.ts/.web.ts file-suffix overrides rather than runtime Platform.OS branching in the hot path, so the core orchestration logic in src/core and src/utils stays platform-agnostic; changing the shared ctx/state contract would ripple through nearly every file in components and core since both layers read and write it directly.

Tech Stack Legend List ships as pure TypeScript with a single runtime dependency (use-sync-external-store) and a peer dependency on react; React Native, Reanimated, and react-native-keyboard-controller integrations are optional peer dependencies activated only through their own subpath entrypoints. The build pipeline uses tsup (configured in tsup.config.ts) with custom prebuild.ts/postbuild.ts scripts to produce separate react, react-native, section-list, animated, reanimated, and keyboard bundles as distinct package exports, and Bun is the primary task runner for installs, builds, and tests. Example consumers are maintained directly in the repo — an Expo app (example/, plus an old-architecture variant) and a Vite-based web playground (example-web/) — giving contributors a way to exercise both native and web code paths against the same source.

Code Quality The repo carries an extensive Jest/React Native Testing Library suite under __tests__ that mirrors the src layout (components, core, hooks, integrations, platform, section-list, state, utils), with contributor guidance in AGENTS.md explicitly requiring regression tests for any change touching scroll adjustment, bootstrapping, or measurement logic. Biome enforces formatting and linting across src, tests, and the example apps, and the codebase is written in strict TypeScript with dedicated typed-wrapper helpers (typedForwardRef, typedMemo in types.internal.ts) to keep generic list-item types sound through forwardRef/memo. The one gap is automation: there is no GitHub Actions workflow in .github/workflows (only a FUNDING.yml), so lint/test/build verification currently relies on contributor discipline rather than an enforced CI gate.

API Design The public API is deliberately shaped to be a near drop-in swap for FlatList/FlashList — same data, renderItem, keyExtractor, header/footer, and viewability props — so migrating an existing list usually means changing an import and opting into a couple of new props. Performance-sensitive behaviors are explicit and opt-in rather than implicit: recycleItems triggers a dev-mode warning when left unset precisely because it changes component lifecycle semantics, and higher-level conveniences like maintainScrollAtEnd, maintainVisibleContentPosition, and alignItemsAtEnd accept both a boolean shorthand and a detailed options object for finer control. An imperative ref (createImperativeHandle) exposes scrollToIndex/scrollToOffset/scrollToEnd, and generics on LegendListRenderItemProps<T> keep item types checked end-to-end, while the linked documentation site (legendapp.com/open-source/list) covers the fuller prop surface beyond the README.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search