Предотвратить рендеринг FlatList, когда numColumns> 1 - PullRequest
1 голос
/ 30 января 2020

Я использую FlatList в собственном проекте реакции для отображения вида сетки изображений, которая представляет очередь загрузки.

<FlatList
  extraData={this.state.images}
  data={this.state.images}
  renderItem={this.renderItem}
  keyExtractor={image => {
   return image.id;
  }}
/>



renderItem = ({item, index}) => {

    return (
      <TouchableOpacity
        id={item.id}
        delayLongPress={500}
        //onLongPress={() => this.props.onLongPressImage(item)}
      >
        <SingleImage
          onFinishUpload={this.props.onFinishUpload}
          index={index}
          item={item}
          title={this.props.title}
        />
      </TouchableOpacity>
    );
};

Как только я установил numColumns> 1 каждый раз, когда изображение добавляется или удаляется другие изображения визуализируются, и componendDidMount класса SingeImage срабатывает.

Это проблема, потому что я начинаю загрузку определенного изображения в componendDidMount () и каждый раз, когда загрузка проходит успешно, изображение удаляется из FlatList , Все остальные загружаемые изображения перемонтируются и перезапускают процесс загрузки.

Если я просто отображаю одну строку, а numColumns не установлена, каждый элемент списка отображается только один раз, и все работает нормально.

Я что-то пропускаю или как я могу предотвратить повторный рендеринг списка каждого элемента, который модифицирует массив данных?

1 Ответ

1 голос
/ 03 февраля 2020

Во-первых, важно помнить разницу между повторным рендерингом и перемонтированием. Это прекрасно компоненты (SingleImage в вашем случае) для повторного рендеринга, но не прекрасно для их перемонтирования, потому что в этом случае компоненты уничтожаются и воссоздаются и, конечно, теряют состояние

Теперь точка: FlatList extends VirtualizedList

Виртуализация значительно повышает потребление памяти и производительность больших списков, поддерживая конечное окно рендеринга активных элементов и заменяя все элементы за пределами окна рендеринга с пустым пространством соответствующего размера

В двух словах, FlatList не создает и сохраняет все экземпляры компонента, которые вы создаете для рендеринга. Представьте себе список из 10000 элементов, он НЕ создаст 10000 экземпляров SingleImage и сохранит их в живых. Вместо этого он создаст только несколько из них (обычно столько, сколько помещается на экране), и при прокрутке результат предыдущего рендеринга будет отброшен, и эти «слоты» будут повторно использованы для элементов с другими данными. В этом суть виртуализации, которая позволяет отображать бесконечно большие списки, рисуя только небольшую часть данных.

«Рисование» является ключевым моментом здесь (вот почему опора называется renderItem, а не Item ). Он просто нарисует что-то на «слоте» и забудет об этом. По этой причине вы не можете визуализировать компоненты с сохранением состояния в renderItem FlatList. Внутреннее состояние этих элементов не сохраняется при повторном рендеринге

. Правильный способ сделать это - обработать загрузку изображений вне FlatList и использовать FlatList только для рисования пользовательского интерфейса с компонентами без сохранения состояния. В качестве более дешевой альтернативы, если вы действительно хотите сохранить логи c и презентацию внутри одного SingleImage компонента, вы можете использовать this.state.images.map вместо FlatList (как вы сделали бы это в React web), чтобы убедиться, что все элементы отображаются в то же время и сохраняют свою идентичность при повторном рендеринге

Причина, по которой он не работает без набора numColumns реквизита, я полагаю, объясняется тем, что numColumns запускает некоторые дополнительные повторные рендеры , но с дополнительным повторным рендерингом прекрасно и не является проблемой root. По сути, без numColumns вам просто везет, потому что в списке недостаточно элементов для виртуализации. Если вы добавите еще несколько предметов, вы увидите тот же эффект даже без numColumns

...