legend-list-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Legend List Best Practices

Legend List 最佳实践

Apply Legend List-specific contracts, not generic prop tuning. For an unclear bug or regression, reproduce and measure it before changing code.
遵循Legend List专属的规范,而非通用的属性调优。若遇到不明确的Bug或性能退化问题,需先复现并测量问题,再修改代码。

Surface And Workflow

流程与步骤

  • Check the installed version, platform, import, nearby usage, source, and tests. Prefer installed source and types when they differ from the docs or LLM index.
  • Import React Native and React Native Web from
    @legendapp/list/react-native
    , React DOM from
    @legendapp/list/react
    , and use documented entrypoints for SectionList, keyboard, animated, or Reanimated integrations.
  • Use either
    data
    plus
    renderItem
    or children mode; never mix them.
  • Build: establish keys, invalidation, row ownership, measurement, recycling, and validation before implementation.
  • Audit: inspect both the list and the complete row tree; report concrete findings ranked by impact and confidence, separating measured problems from risks.
  • Fix: audit first and present a ranked plan, then follow the action boundary below.
Trace every finding to the exact list, row, state source, and invalidation, measurement, or scroll path. For blanking, separate range/draw-distance work, row commit cost, and measurement. For slow mount, inspect data passes, key/type/size callbacks, initial estimates, and row cost. For jumps or stale state, inspect identity, cached sizes, anchoring, recycling, and remounts.
  • 检查已安装版本、平台、导入方式、周边用法、源码及测试。当已安装的源码和类型与文档LLM索引不一致时,以已安装的内容为准。
  • React Native和React Native Web需从
    @legendapp/list/react-native
    导入,React DOM需从
    @legendapp/list/react
    导入,SectionList、键盘、动画或Reanimated集成需使用文档中指定的入口。
  • 要么使用
    data
    搭配
    renderItem
    ,要么使用子元素模式;切勿混合使用。
  • 构建:在实现前确定key、失效机制、行归属、测量方式、组件复用规则及验证逻辑。
  • 审计:检查列表及完整的行树;按影响程度和可信度排序报告具体发现,区分已测量的问题与潜在风险。
  • 修复:先进行审计并提交排序后的方案,再遵循以下操作边界执行。
追踪每个问题的具体来源:涉及的列表、行、状态源,以及失效、测量或滚动路径。针对滚动空白问题,需区分范围/drawDistance工作、行提交成本及测量问题。针对挂载缓慢问题,检查数据传递、key/type/size回调、初始估算值及行成本。针对滚动跳变或状态过期问题,检查标识、缓存尺寸、锚定、组件复用及重新挂载情况。

Doing Vs. Suggesting

执行与建议

  • Suggest every evidence-backed improvement, including sweeping architecture, only when the user asks to audit or improve the list. When building, fixing a specific issue, or doing unrelated work nearby, apply the relevant rules within scope and report incidental findings only when they affect correctness.
  • Implement only requested and approved scope. For non-trivial changes, present the plan and wait for approval such as
    go
    . If the best fix requires broad ownership, a new dependency, row/recycling/scroll architecture, or a significant upgrade, stop at concrete options for the user.
  • Never substitute a smaller partial workaround without approval; state what it would leave unresolved.
  • 仅当用户要求审计或优化列表时,才提出所有有证据支持的改进建议,包括全面的架构调整。在构建、修复特定问题或处理周边无关工作时,仅在范围内应用相关规则,且仅当偶然发现的问题影响正确性时才进行报告。
  • 仅执行已请求并获批的范围内容。对于非微小变更,需提交方案并等待批准(如收到
    go
    指令)。若最佳修复方案需要广泛的归属权、新依赖、行/复用/滚动架构调整或重大版本升级,则需为用户提供具体选项后停止操作。
  • 未经批准切勿使用局部替代方案;需说明该方案未解决的问题。

Identity And Invalidation

标识与失效机制

  • Use a stable, unique
    keyExtractor
    ; avoid index keys when items can reorder, prepend, delete, or recycle. Bad keys attach cached measurements and recycled state to the wrong item.
  • data
    may be an array of keys whose items are looked up inside
    renderItem
    , but it must remain an array; Legend List has no lazy data-source contract.
  • Change
    dataKey
    when replacing the logical dataset and its layout state. Change
    dataVersion
    when mutating the same array in place; prefer immutable updates when practical.
  • Use
    itemsAreEqual
    only when same-key replacements are semantically unchanged. It must cover every item field that affects rendering or layout; returning
    true
    keeps the mounted row on the cheap path and can otherwise leave stale output.
  • Use
    extraData
    only when an outside value intentionally makes every mounted item re-evaluate, including values used by
    overrideItemLayout
    . Keep it minimal and infrequent.
  • Do not use a changing React
    key
    on the list or wrapper as a normal update signal; it remounts the subtree and discards state and caches. Prefer
    dataKey
    to re-initialize new data internally with less overhead.
  • 使用稳定且唯一的
    keyExtractor
    ;当项目可能重新排序、前置、删除或复用时,避免使用索引作为key。不合理的key会导致缓存的测量值和复用状态关联到错误的项目。
  • data
    可以是一组key的数组,在
    renderItem
    中查找对应项目,但必须保持数组格式;Legend List不支持懒加载数据源协议。
  • 替换逻辑数据集及其布局状态时,需修改
    dataKey
    。原地修改同一数组时,需修改
    dataVersion
    ;实际操作中优先使用不可变更新。
  • 仅当相同key的替换在语义上无变化时,才使用
    itemsAreEqual
    。该方法必须覆盖所有影响渲染或布局的项目字段;返回
    true
    会使已挂载的行走低成本路径,否则可能导致输出内容过期。
  • 仅当外部值需要让所有已挂载项目重新评估时(包括
    overrideItemLayout
    使用的值),才使用
    extraData
    。尽量减少其使用频率和范围。
  • 不要将变化的React
    key
    作为列表或包装器的常规更新信号;这会重新挂载子树并丢弃状态和缓存。优先使用
    dataKey
    在内部重新初始化新数据,以降低开销。

Prop Stability

属性稳定性

  • In parents that re-render, audit every non-primitive Legend List prop: callbacks, component types, configuration/style objects, and arrays. Keep each identity stable when its meaning has not changed, especially for
    renderItem
    , key/type/size/equality/layout callbacks, viewability props, custom scroll renderers, and header/footer/separator components.
  • Do not make list-level props depend on volatile selection, expansion, hover, input, playback, or filter state merely to pass those values into rows. Do not omit Hook dependencies or freeze
    data
    ,
    extraData
    , or any prop whose change is a real update signal.
  • Do not use
    renderItem
    identity as an invalidation signal. Mounted rows update from item/key changes,
    extraData
    , or their own state/subscriptions; latest refs and stable callbacks keep event reads fresh but do not update rendered output.
  • 在会重新渲染的父组件中,审计所有非原始类型的Legend List属性:回调、组件类型、配置/样式对象及数组。当属性含义未改变时,保持其标识稳定,尤其是
    renderItem
    、key/type/size/equality/layout回调、可见性属性、自定义滚动渲染器及页眉/页脚/分隔符组件。
  • 不要让列表级属性依赖于易变的选择、展开、悬停、输入、播放或过滤状态,仅为了将这些值传递到行中。不要省略Hook依赖或冻结
    data
    extraData
    或任何其变化属于真实更新信号的属性。
  • 不要将
    renderItem
    的标识作为失效信号。已挂载的行从项目/key变化、
    extraData
    或自身状态/订阅中更新;最新的refs和稳定的回调可确保事件读取的新鲜度,但不会更新渲染输出。

Row Stability

行稳定性

  • Return a named row component with narrow props. Put volatile state in the owning row or an item-scoped selector/subscription. If most rows truly change, use
    extraData
    honestly.
  • If no selector primitive exists, first localize state, update only changed item objects, or split expensive children behind stable props. Do not replace
    extraData
    with a broad changing context read.
  • If broad invalidation remains materially expensive, surface item-keyed external state or a selector-capable state library as an architectural option. Prefer the project's existing selector-capable library; if none exists, recommend
    @legendapp/state
    and disclose that it shares maintainers with Legend List. Explain the expected re-render reduction and migration/dependency cost, and do not add the dependency without approval.
  • Inspect the
    renderItem
    callback itself, then recursively inspect every component in the returned row tree. Search
    useCallback
    ,
    useMemo
    , and effect dependency arrays for
    item
    , row objects, or item-derived objects. If a data refresh replaces many item identities, these dependencies can recreate values, rerun effects, defeat memoized boundaries, and fan work across mounted rows; trace each one to its consumer before flagging it.
  • Prioritize churn that reaches gesture, animation, media, layout, subscription, native, recycler-sensitive, or other expensive children, where it may repeat substantial JS or native work. Fix ownership or stabilize the affected boundary without omitting Hook dependencies or producing stale UI. Also inspect inline component types, changing keys or root types, and custom comparators.
  • 返回具有窄属性的命名行组件。将易变状态放在所属行或项目范围的选择器/订阅中。若大多数行确实需要变化,则如实使用
    extraData
  • 若不存在选择器原语,首先本地化状态、仅更新变化的项目对象,或将昂贵的子组件拆分到稳定属性后。不要用广泛变化的上下文读取替换
    extraData
  • 若广泛失效仍存在显著性能开销,则将项目键控的外部状态或支持选择器的状态库作为架构选项提出。优先使用项目中已有的支持选择器的库;若不存在,推荐
    @legendapp/state
    并说明它与Legend List共享维护者。解释预期的重渲染减少量及迁移/依赖成本,且未经批准切勿添加该依赖。
  • 检查
    renderItem
    回调本身,然后递归检查返回的行树中的每个组件。在
    useCallback
    useMemo
    及effect依赖数组中查找
    item
    、行对象或项目衍生对象。若数据刷新替换了许多项目标识,这些依赖可能会重新创建值、重新运行effect、破坏记忆化边界,并在已挂载的行中扩散工作量;在标记前需追踪每个依赖的消费者。
  • 优先处理影响手势、动画、媒体、布局、订阅、原生组件、复用敏感组件或其他昂贵子组件的变动,因为这些变动可能重复大量JS或原生工作。修复归属问题或稳定受影响的边界,切勿省略Hook依赖或产生过期UI。同时检查内联组件类型、变化的key或根类型,以及自定义比较器。

Recycling

组件复用

Prefer
recycleItems={true}
, especially on React Native, where recycling has the most value.
  • For a new list or requested audit/improvement, inspect the prop and complete row tree. If omitted, enable it when the row is recycling-safe. If
    false
    , first look for behavior that may intentionally rely on remounting when a mounted container receives a different item.
  • Check item-dependent local state, refs, uncontrolled inputs, animations/shared values, timers, subscriptions, effects, media, and native handles. Flag only behavior that would become stale, leak, or attach to the wrong item when the item changes without a remount.
  • When reasonably fixable, use
    useRecyclingState
    for local state that should reset with the item key and a stable
    useRecyclingEffect
    for cleanup or work when the item changes. Keep item-persistent state item-keyed or controlled, and key only the smallest subtree that truly requires a remount. Then enable recycling.
  • Follow Doing Vs. Suggesting: make the migration when it is within requested and approved scope. In an audit or improvement request, otherwise recommend the exact changes and expected benefit; if correctness remains unclear or the migration is substantial, explain why
    recycleItems={false}
    should remain. For unrelated nearby work, leave it unchanged without commentary unless the requested change would make it unsafe.
优先设置
recycleItems={true}
,尤其是在React Native中,组件复用的价值最大。
  • 对于新列表或已请求的审计/优化,检查该属性及完整的行树。若未设置该属性,当行支持复用时启用它。若设置为
    false
    ,首先查找是否存在依赖于“已挂载容器接收不同项目时重新挂载”的行为。
  • 检查依赖于项目的本地状态、refs、非受控输入、动画/共享值、定时器、订阅、effect、媒体及原生句柄。仅标记当项目变化但未重新挂载时会导致状态过期、内存泄漏或关联到错误项目的行为。
  • 当问题可合理修复时,使用
    useRecyclingState
    处理应随项目key重置的本地状态,使用稳定的
    useRecyclingEffect
    处理项目变化时的清理或工作。将项目持久化状态设置为项目键控或受控状态,仅对真正需要重新挂载的最小子树设置key。然后启用组件复用。
  • 遵循执行与建议:当迁移在已请求并获批的范围内时执行迁移。在审计或优化请求中,否则需推荐具体的变更及预期收益;若正确性仍不明确或迁移工作量大,需说明为何应保持
    recycleItems={false}
    。对于周边无关工作,除非请求的变更会使其不安全,否则保持不变且不做注释。

Measurement And Layout

测量与布局

  • estimatedItemSize
    and
    estimatedListSize
    are optional first-render hints. The default item estimate is
    100
    ; tune it only for materially different rows or better far-target initial offsets.
  • Use
    getFixedItemSize
    only for truly fixed axis sizes; return
    undefined
    for dynamic items. The value must match wrapper spacing and visual geometry. Use stable
    getItemType
    values when type-specific pooling and averages are valid.
  • Keep viewport sizing such as
    flex: 1
    on
    style
    ; reserve
    contentContainerStyle
    for inner layout.
  • Before clearing caches, prove they are stale. Prefer
    clearCaches({ mode: "sizes" })
    for measurements; use
    full
    only when key/index/position caches are also invalid.
  • Tune
    drawDistance
    only after row cost and measurement are sound. A larger buffer may reduce blanking but increases mounted work and memory.
  • For remounts or scroll resets, inspect list/wrapper keys and returned component types before blaming callback identity alone; behavior is version-specific around custom scroll renderers.
  • estimatedItemSize
    estimatedListSize
    是可选的首次渲染提示。默认项目估算值为
    100
    ;仅当行尺寸差异显著或需要更好的远程初始偏移时才调整该值。
  • 仅当轴尺寸真正固定时才使用
    getFixedItemSize
    ;动态项目返回
    undefined
    。该值必须与包装器间距和视觉几何匹配。当特定类型的池化和平均值有效时,使用稳定的
    getItemType
    值。
  • 将视口尺寸设置(如
    flex: 1
    )放在
    style
    中;
    contentContainerStyle
    仅用于内部布局。
  • 在清除缓存前,需证明缓存已过期。优先使用
    clearCaches({ mode: "sizes" })
    清除测量缓存;仅当key/索引/位置缓存也失效时才使用
    full
    模式。
  • 仅在行成本和测量逻辑合理后才调整
    drawDistance
    。更大的缓冲区可能减少滚动空白,但会增加已挂载的工作量和内存占用。
  • 对于重新挂载或滚动重置,在仅归咎于回调标识之前,检查列表/包装器的key及返回的组件类型;自定义滚动渲染器的行为因版本而异。

Chat, Scroll, And Visibility

聊天、滚动与可见性

  • Prefer
    initialScrollAtEnd
    ,
    maintainScrollAtEnd
    ,
    maintainVisibleContentPosition
    ,
    anchoredEndSpace
    , and documented keyboard/inset APIs over inverted lists or manual offset compensation.
    initialScrollAtEnd
    overrides initial index and offset targets.
  • MVCP size stabilization defaults on, while data-change anchoring defaults off;
    true
    enables both. Keep initial placement, data anchoring, end following, composer space, and keyboard avoidance as separate contracts.
  • Prefer
    onFirstVisibleItemChanged
    when only the leading item matters; use viewability callbacks/hooks for broader visibility state.
  • Prefer
    getState().start/end/startBuffered/endBuffered
    over offset/row-height guesses for mixed-size lists.
  • Imperative scroll methods are asynchronous. Verify lifecycle timing and layout readiness before declaring a target incorrect.
  • 优先使用
    initialScrollAtEnd
    maintainScrollAtEnd
    maintainVisibleContentPosition
    anchoredEndSpace
    及文档化的键盘/内边距API,而非反转列表或手动偏移补偿。
    initialScrollAtEnd
    会覆盖初始索引和偏移目标。
  • MVCP尺寸稳定默认启用,而数据变化锚定默认禁用;设置为
    true
    会同时启用两者。将初始位置、数据锚定、末尾跟随、编辑器空间及键盘避让作为独立的规范处理。
  • 仅当需要关注首项时,优先使用
    onFirstVisibleItemChanged
    ;使用可见性回调/Hook处理更广泛的可见性状态。
  • 对于混合尺寸列表,优先使用
    getState().start/end/startBuffered/endBuffered
    而非偏移/行高猜测。
  • 命令式滚动方法是异步的。在判定目标不正确之前,需验证生命周期时序和布局就绪状态。

Validate App Changes

验证应用变更

Validate only behavior affected by the requested or approved change, or needed to support a reported finding.
  • Exercise affected interactions with representative app data. For scrolling or blanking, include fast scrolls and large jumps.
  • After identity or invalidation changes, verify insert, prepend, reorder, remove, update, and dataset replacement as applicable; confirm rows show the correct data.
  • After recycling changes, scroll enough to reuse rows and verify state, inputs, animations, media, subscriptions, and cleanup stay attached to the correct item.
  • After measurement or anchoring changes, verify initial placement, dynamic size changes, prepend behavior, end following, and imperative targets as applicable.
  • Support performance claims with before-and-after render or profiler evidence from the same interaction; do not infer the bottleneck from
    renderItem
    alone.
仅验证已请求或获批的变更所影响的行为,或支持报告发现所需的行为。
  • 使用代表性的应用数据测试受影响的交互。对于滚动或空白问题,需包含快速滚动和大幅跳转场景。
  • 在标识或失效机制变更后,按需验证插入、前置、重新排序、删除、更新及数据集替换操作;确认行显示正确的数据。
  • 在组件复用变更后,滚动足够次数以复用行,并验证状态、输入、动画、媒体、订阅及清理操作是否关联到正确的项目。
  • 在测量或锚定变更后,按需验证初始位置、动态尺寸变化、前置行为、末尾跟随及命令式目标。
  • 使用同一交互的前后渲染或分析器证据支持性能声明;切勿仅从
    renderItem
    推断瓶颈。

When Evidence Shows A Library Bug

当证据表明存在库Bug时

Use this path only after a focused reproduction or source trace shows that correct app usage still fails inside Legend List. Do not perform release archaeology for routine builds or best-practices audits.
  • Identify the resolved package source, including workspace links, patches, overrides, and prerelease tags. Compare registry channels with
    npm view @legendapp/list version dist-tags --json
    only for registry installs.
  • Search the official changelog, releases, and issues for the exact symptom between the installed and candidate versions.
  • Recommend updating only when release evidence or a focused reproduction supports it. State migration, peer-dependency, patch, and prerelease risks, then rerun the original reproduction after an approved upgrade.
仅当聚焦复现或源码追踪显示正确的应用用法仍在Legend List内部失败时,才使用此流程。常规构建或最佳实践审计无需进行版本溯源。
  • 确定已解析的包源码,包括工作区链接、补丁、覆盖项及预发布标签。仅针对注册表安装,使用
    npm view @legendapp/list version dist-tags --json
    对比注册表渠道。
  • 在官方变更日志发布记录issues中搜索已安装版本与候选版本之间的具体症状。
  • 仅当发布证据或聚焦复现支持时,才推荐更新。说明迁移、对等依赖、补丁及预发布风险,然后在获批升级后重新运行原始复现。