react / react/react-native

SectionList unnecessarily unmounts and mounts items when filtering (in between renders)

Aperta
#28,919 25 commenti 15 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Component: SectionList Needs: Attention Platform: Android
Lingua principale
C++
Stelle
127k
Fork
25.3k
Merge medio
1g 23h
PR unite (30g)
4

Descrizione

Description

When a SectionList rerenders, sometimes it unmounts and remounts some of its items unnecessarily, even though the items preserve the same "key" prop in between renders. This impacts performance.

A scenario where this could happen is when filtering data. Imagine a SectionList with a search bar (TextInput) above it. Every time the user types something in the search bar, the section list gets filtered so it shows the items that contain the text in the search bar. Sometimes, the items get remounted unnecessarily when typing (Why remount an item when it was already there? It passed the filter, it should stay there.)

React Native version:

System:
OS: Windows 10 10.0.18363
CPU: (8) x64 Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
Memory: 6.52 GB / 15.87 GB
Binaries:
Node: 12.14.0 - C:\Program Files\nodejs\node.EXE
Yarn: Not Found
npm: 6.13.4 - C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK: Not Found
IDEs:
Android Studio: Version 3.6.0.0 AI-192.7142.36.36.6392135
Languages:
Java: Not Found
Python: 2.7.17 - C:\Python27\python.EXE
npmPackages:
@react-native-community/cli: Not Found
react: 16.11.0 => 16.11.0
react-native: 0.62.2 => 0.62.2
npmGlobalPackages:
react-native: Not Found

Steps To Reproduce

  1. Create a new react-native project. npx react-native init sectionlisttest
  2. Modify the App.js file so it looks like the following.
import React, {useEffect, useState} from 'react';
import {SectionList, Text, View} from 'react-native';

const originalData = [{
  key: 'header1',
  header: 'Header 1',
  data: [{key: 'firstItem'}, {key: 'byebye1'}],
}];

const filteredData = [{
  key: 'header1',
  header: 'Header 1',
  data: [{key: 'firstItem'}],
}];

export default function App() {
  useEffect(() => {
    setTimeout(() => setSections(filteredData), 5000);
  }, []);

  const [sections, setSections] = useState(originalData);

  return (
    <SectionList
      sections={sections}
      renderItem={renderItem}
      renderSectionHeader={renderSectionHeader}
      ItemSeparatorComponent={Separator}
    />
  );
}

const renderItem = ({item}) => <Item item={item} />;

const Item = ({item}) => {
  useEffect(() => {
    console.log('item mounted');
  }, []);
  return <Text>{item.key}</Text>;
};

const renderSectionHeader = ({section}) => <Text>{section.header}</Text>;

const Separator = () => <View style={{height: 1, backgroundColor: 'black'}} />;
  1. Run the app. I ran it in Android (npx react-native run-android).

IMPORTANT: Fully reload the app, don't depend on hot reloading.

Expected Results

Expected result: 2 lines saying "Item mounted" get printed to the logs.

Actual Result: 2 lines saying "Item mounted" get printed to the logs. . But then, 5 seconds later, it prints a third line also saying "Item mounted".

Snack, code example, screenshot, or link to a repository:

Snack: https://snack.expo.io/@hectorricardo/sectionlist-bug

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Riproduci il comportamento dell’esempio App.js o dello Snack collegato, usando la transizione dei dati di SectionList dopo cinque secondi. Traccia quali elementi vengono montati durante l’aggiornamento e rivedi il comportamento di rendering e la gestione delle key di SectionList. Il lavoro è completato quando il filtraggio o l’aggiornamento delle sezioni non esegue più inutilmente il mount di un elemento che mantiene la stessa key, con un test di regressione che copra lo scenario.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
javascript, react-native
Ambito
mobile
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Tranquilla
Chiarezza
Abbastanza chiara
Idoneità per principianti
48/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.