React Native / Editorial solution guide

Diagnose FlatList selection and row lifetime

Locate identity, shallow-update, and virtualization ownership defects before changing list tuning.

About 3 min readContent reviewed

Read-only knowledge base ยท No public comments

Recognize the symptoms

Selection moves to another record after sorting or front insertion, a row ignores an external selection change, or a typed draft disappears after scrolling away.

The titles may all look correct, so a screenshot alone misses that state belongs to the wrong logical record.

Understand the likely causes

  • Index keys identify positions rather than domain records. Duplicate or freshly generated keys also violate the intended identity contract.
  • FlatList shallow prop comparison and offscreen row removal expose missing external dependencies or durable state stored only inside a disposable row.

Reproduce a movement with a recognizable record

Use a tiny synthetic collection with stable identifiers and different titles. Select or edit one record, then reorder, insert before it, remove it, and return after leaving the render window. Record the identifier that should own the draft rather than only its current index. Distinguish incorrect identity from a correct page-local policy that deliberately clears unavailable selections. Preserve the minimal reproduction before changing windowSize or batch settings; those performance controls do not repair a selection model that names the wrong record.

Validate identity before passing records to the list

Use a stable domain key in keyExtractor and reject duplicate identifiers at the data boundary. The standalone diagnostic program builds an index and detects a collision instead of silently overwriting a legitimate record. A display title can change or repeat, so it is not a general substitute for identity. Do not generate random keys during render to remove a warning. The program tests local key policy only; it does not mount FlatList or prove React reconciliation. Real row movement still needs the configured component or target host.

javascript Standalone JavaScript model with synthetic local inputs.
function indexRecords(rows) {
  const index = new Map();
  for (const row of rows) {
    if (index.has(row.id)) throw new Error('DUPLICATE_ID');
    index.set(row.id, row);
  }
  return index;
}
console.log(indexRecords([{id: 'w-7', title: 'Maps'}]).get('w-7').title);
try { indexRecords([{id: 'w-7'}, {id: 'w-7'}]); }
catch (error) { console.log(error.message); }
Expected output
Maps
DUPLICATE_ID

The model accepts already validated record shapes and checks collection uniqueness. It performs no renderer or native-list operation.

Make render dependencies and durable ownership explicit

If rows depend on selected identifiers outside data, use immutable values and an explicit extraData contract rather than relying on incidental callback recreation. A durable draft should live above disposable rows under its record identifier. Native virtualization can remove an offscreen row, so local row state is not a persistence guarantee. Keep a deliberate policy for an item that disappears during refresh and for selection spanning multiple pages. These are separate choices: preserving row identity does not automatically choose whether hidden or deleted records remain selected.

Verify movement, dependency changes, and accessible layout

In the compatible host, test selection with unchanged data, reordered data, a removed record, and a row that leaves and reenters the render window. Confirm each draft follows its intended identifier and lifetime. Include long Arabic text, large font scale, and empty or failed refresh states. Do not repair dynamic-height scrolling by supplying guessed getItemLayout offsets; validate actual dimensions or keep measurement. Compare a pure selection model separately from component and device evidence. A passing Map test cannot establish scroll position, native recycling, touch handling, or assistive focus.

Verify the fix

The repaired contract preserves state through supported movement, exposes external selection updates, and applies the documented missing-record policy. Duplicate identifiers are rejected before rendering.

Report the standalone index check as local model evidence. Native/JSX examples, renderer behavior, list scrolling, and device accessibility remain unexecuted in this course environment.

Keep it from recurring

  • Document stable identity, external row dependencies, and durable draft lifetime together. Keep the edited-row reorder fixture and profile tuning only after correctness is established.

Official references