React-window: Поддержка содержания, измеряемого точно в срок

Созданный на 30 мая 2018  ·  132Комментарии  ·  Источник: bvaughn/react-window

Чтобы избежать увеличения стоимости существующих компонентов списка и сетки, создайте новый вариант (например, DynamicSizeList и DynamicSizeGrid ). Этот вариант должен автоматически измерять свое содержимое на этапе фиксации.

MVP

Первоначальная реализация этого может работать аналогично тому, как CellMeasurer работает в react-virtualized:

  1. Контент измеряется только в том случае, если текущие измерения отсутствуют.
  2. Если что-то изменится, измерения необходимо сбросить извне (обязательно).
  3. Ячейки с заданным индексом могут быть размещены только после того, как будут измерены все ячейки до этого индекса.

Цель

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

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

Для того, чтобы вышеперечисленное было возможным, компоненты динамического списка / сетки должны использовать совершенно другой подход для сопоставления смещения с индексом и наоборот. ( Этот комментарий о «привязке прокрутки» в react-virtualized имеет несколько хороших визуальных эффектов.) По сути, нам нужно будет сделать что-то вроде этого:

  • Оцените общий размер, основываясь на количестве элементов, умноженном на опору estimatedItemSize . (Этот приблизительный размер не нужно изменять, поскольку описанное ниже сопоставление не является нечетким.)

  • При изменении положения прокрутки сравните новое смещение с предыдущим. Если дельта больше некоторого [предстоит определить] порога , установите новое смещение как «привязку прокрутки». Сопоставьте смещение с оценочным индексом (например, разделите смещение на общий предполагаемый размер с возможностью прокрутки и умножьте его на количество элементов в коллекции). Сохраните этот сопоставленный индекс как «индекс привязки». Например, если список, описанный на изображении ниже, содержит 250 элементов, «индекс привязки» будет равен 132.

screen shot 2018-06-10 at 11 58 38 am

  • При изменении положения прокрутки, если дельта меньше порогового значения , выберите, какие новые элементы отображать относительно индекса привязки. Разместите эти элементы относительно ранее размещенных элементов. Продолжая приведенный выше пример, если список был прокручен на небольшую величину (200 пикселей), то под ранее размещенными элементами необходимо будет добавить дополнительные строки на 200 пикселей:

screen shot 2018-06-10 at 12 01 01 pm

У описанного выше подхода есть только один серьезный недостаток: правильное выравнивание элементов по границам списка. Если индексы элементов оцениваются (как описано выше), они, вероятно, не будут точно совпадать с началом или концом прокручиваемой области.

  • Конец потенциально может быть объяснен путем корректировки общего предполагаемого размера по мере того, как пользователь прокручивает ближе к концу (хотя это может сделать прокрутку неудобной).
  • С началом списка труднее справиться, так как первый элемент должен быть выровнен по нулевому смещению, но при этом он все еще отображается для непрерывного соединения с элементами с некоторым смещением больше нуля. Возможно, можно было бы использовать другой порог, «безопасную зону», около начала списка (например, если смещение прокрутки меньше некоторого абсолютного значения), что заставило бы список измерять все ячейки до этой точки, чтобы они правильно выровнялись. Стоимость этого принудительного измерения будет относительно невысокой, так как это будет лишь небольшое количество элементов.
    screen shot 2018-06-10 at 5 04 42 pm

Единственный случай, который все еще не будет обработан правильно с помощью вышеупомянутого подхода, - это привязка прокрутки, которая установлена ​​за пределами «безопасной зоны», но текущая прокрутка, которая проходит внутри безопасной зоны (как показано ниже). Если пользователь медленно прокручивает назад к началу списка, может быть трудно выровнять первую ячейку с нулем, не вызывая дерганую прокрутку.
screen shot 2018-06-10 at 5 08 26 pm

👋 help wanted

Самый полезный комментарий

В этом проекте нет «вы, ребята». Его обслуживает один человек.

И довольно невнимательно оставлять в один день комментарии по нескольким вопросам, жалуясь на одно и то же. Во что бы то ни стало, просто используйте react-virtualized.

Все 132 Комментарий

Незавершенная работа над MVP доступна по адресу https://github.com/bvaughn/react-window/compare/master...issues/6

Я использую это в mui-downshift и в настоящее время все еще использую UNSAFE_componentWillReceiveProps , хотя в ближайшем будущем я планирую попытаться портировать на react-window (как только станет доступна высота динамического содержимого).

это многоразовый механизм в UITableView в IOS?

@luoboding Я не понимаю вашего вопроса. Не могли бы вы уточнить?

@bvaughn извини, друг мой, мой английский не очень хорош.

У меня проблема в моем проекте, у меня есть тысячи вариантов в элементе select, он становится очень медленным и застревает при перезагрузке страницы, я попытался написать компонент, чтобы сделать его лучше, я был разработчиком IOS, я знаю механизм многократного использования в UITableView в IOS, если мне нужен элемент выбора высоты 500 пикселей, я настраиваю высоту элемента опции на 100 пикселей, поэтому мне просто нужно создать (Math.floor (500/100)) количество элементов опции и емкость очереди (текущая отображаемая очередь источника данных ), когда я прокручиваю выбранный элемент вверх или вниз, просто нажимаю или вставляю в очередь, чтобы повторно отобразить его.

Я хочу импортировать окно реакции в свой проект, работает ли оно, как я уже упоминал?

То, что вы описываете, - это то, как работает response-window (и оконное управление или отсечение окклюзии в целом). Однако на самом деле это не связано с этой проблемой. Речь идет о своевременном измерении оконного контента. В вашем случае объекты имеют фиксированную высоту - поэтому вы можете использовать компонент FixedSizeList : https://react-window.now.sh/#/examples/list/fixed -size

Приятно видеть, что привязка изначально адресована в окне реакции.

Кстати, извините, если я слишком сильно поднял планку на диаграммах……

@bvaughn когда вы выпустите эту функцию, я ищу это

Я опубликовал 1.0.0 без этой функциональности, потому что мне трудно найти время (и силы), чтобы закончить это прямо сейчас. Еще планирую добавить в будущем. Нет оценок, когда.

Похоже, что в «железном списке» Polymer используется та же техника, что и я предлагаю здесь: https://github.com/domenic/infinite-list-study-group/blob/master/studies/Polymer-iron-list.md #virtual -list -sizing

это было бы действительно полезно для нас, прямо сейчас кажется, что мы должны синхронизировать CSS с логикой компонента, которая дублирует вычисление высоты, просто чтобы передать его в виртуальный список.

@kevinder, не могли бы вы рассказать, как вы

@carlosagsmendes не уверен, поможет ли это, но вот что я делаю, используя это для отображения истории чата:

1.) В конструкторе создайте ссылку для списка и для моего компонента ChatHistory :

  constructor(props) {
    super(props);
    this.listRef = createRef();
    this.chatHistoryRef = createRef();
    this.listHeight = 0;
  }

Затем я передаю ссылки в ChatHistory который отвечает за рендеринг списка.

2.) В componentDidMount родительского компонента я использую ChatHistory ref, чтобы получить высоту элемента:

componentDidMount() {
    this.listHeight = this.chatHistoryRef.current.offsetHeight;
}

3.) В родительском компоненте я поддерживаю массив в его состоянии с деталями chathistory. При добавлении нового элемента в этот массив я делаю это так:

  // find out how many pixels in height the text is going to use
  const size = getSize({
    text: displayText,
    className: styles.message,
  });

  let { height } = size;
  height += 20; // adds some spacing in pixels between messages
...rest of items needed for the chat history item..add them all to an array and update state

getSize основан на https://github.com/schickling/calculate-size, но я изменил его для поддержки принятия имени класса. Это тот же класс, который используется в качестве контейнера для отображения отдельных сообщений.

Я уверен, что есть лучший способ добиться этого, но он кажется довольно быстрым, и я еще не столкнулся с какими-либо проблемами

@osdlge : Есть ли шанс, что у вас есть демонстрация этого где-нибудь, где я мог бы проверить - например, Code Sandbox (или что-то подобное)?

@bvaughn конечно, я извлек соответствующие части своего кода на https://codesandbox.io/s/5z282z7q1l

Спасибо, что поделились! 😄

Я перенес некоторую незавершенную работу по начальному подходу к лениво измеряемому контенту в ветку с именем issue / 6.

Я также развернул демонстрацию:
https://react-window-next.now.sh/#/examples/list/dynamic -size

Очень круто.

Я все еще пытаюсь разобраться в общих проблемах с бесконечной прокруткой, просматривая исходный код ветки issue / 6 и это обсуждение. Поэтому вопрос, следующий за вопросом, может не иметь смысла, но вот он, поскольку я действительно хотел бы понять это дальше:

Связано ли вышеупомянутое упоминание о «привязке прокрутки» к привязке прокрутки в качестве метода, как в связанной статье или спецификации привязки прокрутки CSS ?

заранее спасибо

Это как бы косвенно связано с вашей первой ссылкой, но не со второй. Это просто термин, который я решил использовать для обозначения проблемы, потому что он имеет для меня смысл, а не потому, что он связан с какой-либо другой спецификацией или предложением.

Я также опубликовал предварительную версию окна реакции для NPM как «следующий» (например, yarn add react-window@next ).

Вы можете поэкспериментировать с этим, разветвив эту песочницу кода:
https://codesandbox.io/s/5x8vlm0o7n

Я только что это проверил. Я пробовал 10000 абзацев и пытался перейти до конца. Было отрывисто.
Если я правильно понял, он должен был измерить только те строки, которые, по оценкам, находятся в конце, и поэтому он должен был мгновенно прыгнуть до конца. Это правильно?

12 октября 2018 года в 12:53 Брайан Вон [email protected] написал:

Я также опубликовал предварительную версию response-window для NPM как «следующий» (например, yarn add response-window @ next).

Вы можете поэкспериментировать с этим, разветвив эту песочницу кода:
https://codesandbox.io/s/5x8vlm0o7n https://codesandbox.io/s/5x8vlm0o7n
-
Вы получаете это, потому что подписаны на эту ветку.
Ответьте на это письмо напрямую, просмотрите его на GitHub https://github.com/bvaughn/react-window/issues/6#issuecomment-429271555 или отключите поток https://github.com/notifications/unsubscribe-auth/ AOf2h7RmSEyGmyrEdMY6GgyZFjCKlDDFks5ukGafgaJpZM4UTb3P .

Нет, начальная ветвь, которую я отправил, не реализует алгоритм
описано в этом выпуске. Требуется более наивный подход.
измерение более раннего содержимого перед отображением более позднего содержимого

Извините за путаницу!

Пт, 12 октября 2018 г., 18:34 akraines [email protected] написал:

Я только что это проверил. Я попробовал 10000 абзацев и попытался перейти к
конец. Было отрывисто.
Если я правильно понял, он должен был измерить только те строки, которые оцениваются
быть в конце, и поэтому он должен был мгновенно перейти к
конец. Это правильно?

12 октября 2018 года в 12:53 Брайан Вон [email protected] написал:

Я также опубликовал предварительную версию окна реакции для NPM как
"следующий" (например, пряжа добавить окно реакции @ далее).

Вы можете поэкспериментировать с этим, разветвив эту песочницу кода:
https://codesandbox.io/s/5x8vlm0o7n < https://codesandbox.io/s/5x8vlm0o7n

-
Вы получаете это, потому что подписаны на эту ветку.
Ответьте на это письмо напрямую, просмотрите его на GitHub <
https://github.com/bvaughn/react-window/issues/6#issuecomment-429271555>,
или отключить поток <
https://github.com/notifications/unsubscribe-auth/AOf2h7RmSEyGmyrEdMY6GgyZFjCKlDDFks5ukGafgaJpZM4UTb3P
.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/bvaughn/react-window/issues/6#issuecomment-429282228 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AABznR5R1N0ErukleIfvaLQORF_NECgRks5ukHBHgaJpZM4UTb3P
.

Привет,
Хотел спросить, есть ли оценка официального релиза?

Моя команда использует react-virtualized для нового проекта, который мы начали, однако нам нужна функция прокрутки вверх и перехода к определенному индексу строки (поскольку вы можете предположить, что наши строки имеют динамическое содержимое, содержащее изображения и другое изменяющееся содержимое).

Вы бы порекомендовали перейти на react-window в его альфа-версии? Или нам ждать официального релиза?

Также, если есть какой-то способ внести свой вклад в завершение этой функции, я хотел бы помочь 😄

К сожалению, на данный момент я не могу придерживаться графика выпуска, потому что я не проводил много тестирования и не знаю, с какими проблемами я столкнусь, когда это сделаю (или сколько времени потребуется, чтобы исправить их).

Если вы хотите внести свой вклад, одним из способов было бы протестировать альфа-версию и сообщить мне, насколько хорошо она работает, и если вы обнаружите какие-либо ошибки.

Я, вероятно, скоро сосредоточусь на этом подробнее, но не могу сказать, как скоро. В частности, в течение следующих недель или двух я отвлекаюсь на React conf и готовлю релиз 16.6.

@bvaughn отличная работа 👏 Наконец-то есть время поиграть. 🕹

Похоже, нам нужны некоторые настройки при скрытии списка с помощью display: none Например, у вас есть страница с двумя вкладками и вы хотите переключаться между ними без потери текущего состояния (положение прокрутки и т. Д.), Imho это не редкий случай использования .

Простая песочница кода, представляющая проблему:
https://codesandbox.io/s/p7vq18wmjq

Это происходит потому, что, когда мы запускаем display none, у всех дочерних элементов будет offsetHeight === 0
resize наблюдает за kiks и обновляет новые значения. react-window не должны заботиться об этих ситуациях, если вызывающий решил скрыть это, basic должен обработать это, заблокировав handleNewMeasurements

если эта линия
https://github.com/bvaughn/react-window/blob/issues/6/src/DynamicSizeList.js#L443
изменится на

handleNewMeasurements: instance._handleNewMeasurements

тогда мы можем переопределить логику по умолчанию

let _handleNewMeasurements

<DynamicSizeList  
  ref={current => {
    if (current) {
      _handleNewMeasurements = current._handleNewMeasurements
      current._handleNewMeasurements = (...args) => {
        if (!isHidden) {
          return _handleNewMeasurements(...args)
        }
      }
    }
  }}
  {...otherProps}

Я отправил обновление в эту ветку (и опубликовал новый тег @next для NPM), который исправляет ошибку плавной прокрутки Firefox, используя margin-top для учета измененных размеров элементов во время прокрутки. Это сложнее, чем мне бы хотелось, но на данный момент я не знаю лучшего способа справиться с этим. (Мне также нужно провести еще несколько испытаний этого подхода, потому что я думаю, что в крайних случаях у него могут быть некоторые шероховатости.)

Я ценю отзывы выше, @piecyk. У меня еще не было времени вникать в это. (На данный момент для меня это всего лишь побочный проект.)

Похоже, я могу удалить взлом маржи в пользу хотя бы scrollBy для Firefox . Однако сначала нужно протестировать IE и Edge. У них могут быть свои проблемы.

Да @bvaughn, я знаю, отличная работа 👏 Не знаю, как ты находишь время! 🥇 Слава тебе!

Но давайте вернемся к проблеме, когда список находится в каком-то элементе DOM, который скрыт с отображением none, в основном нам нужно проверить, имеет ли оболочка высоту, ширину, если нет, мы не хотим начинать рендеринг (в настоящее время он попытается отобразить весь список) завтра попробую починить (есть кое-что припрятать)

Ага. Я понимаю суть проблемы, которую вы описываете. Мне не нравится идея обойти это путем переопределения / исправления большего количества методов экземпляра, поэтому я хотел бы сначала подумать об этом.

Кажется, пакет @next сломан?

https://codesandbox.io/s/5x8vlm0o7n

Не знаю, подходящее ли это место, чтобы задать вопрос, так что извините, если я ошибаюсь. Итак, вкратце:

  • Я использовал DynamicSizeList вместе с AutoResizer и в целом он отлично работает. Престижность!
  • Меня попросили представить строки, содержимое которых можно расширять (добавляя дополнительный div с дополнительной информацией) и убирать.
  • Я также добавил (через redux) опору для этих строк, которая прослушивает глобальные действия развертывания / втягивания.
  • Начинается веселье. Я нажимаю "развернуть / отозвать", и все выглядит отлично!
  • Если я немного прокручу, а затем разверну / уберу все строки, количество убранных строк будет таким же, как и количество развернутых строк. Если я снова разверну ретракт, число увеличится до половины и так далее.
    (т.е. 30 строк убраны -> 10 развернуты -> щелкните втягивание -> 10 строк втянуты -> щелкните развернуть -> 3 строки развернуты -> щелкните втягивание -> 3 строки убраны).

Я попытался перезагрузить itemData, предоставив другой, но тот же объект с помощью взлома JSON.parse (JSON.stringify (data)). Не повезло :-(

Подозреваю просчет высоты. Есть идеи решить эту проблему?

Не могли бы вы поделиться примером codeandbox? Мне нужно сделать что-то подобное, может, мы сможем помочь друг другу

@vtripolitakis Я только что нашел пример с расширяемыми строками . Вот ссылка на обсуждение

@carlosagsmendes, спасибо за это, но мой пример немного отличается, поскольку я использую DynamicSizeList :-(

Итак, я нашел причину проблемы:
state.scrollOffset принимал отрицательные значения.

на src/DynamicSizeList.js нам нужно добавить следующий код в строку 299

if (sizeDeltaForStateUpdate < 0) {
          sizeDeltaForStateUpdate = 0;
        }

Хм ... Я не ожидал, что это исправление окажется правильным с первого взгляда. Разница в размере может быть отрицательной, не так ли?

Может быть, нам стоит поставить охрану ( Math.max(0, prevState.scrollOffset + sizeDeltaForStateUpdate) ) там, где обновляется значение state.scrollOffset ?

Здравствуйте, пока я отлаживал свой случай, sizeDeltaTotal принимал отрицательные значения и, соответственно, сделал sizeDeltaForStateUpdate отрицательным, давая отрицательное значение state.scrollOffset после обновления состояния.

Это произошло, когда я развернул и убрал элементы, а затем прокрутил их вверх, указав scrollOffset 0 и направление backwards . Затем, если я несколько раз разверну и уберусь, я получу негативы.
Да, ваше предложение должно быть одинаково хорошим. ~ Тестирую прямо сейчас. ~ Работает правильно.

@marcneander попробовать версию 1.4.0-alpha.1

Что касается игнорирования событий изменения размера, когда список скрыт, возможно, что-то вроде этого https://github.com/piecyk/react-window/commit/acfd88822156611cfd38872acdafbbefd2d0f78f
@bvaughn что ты думаешь?

Я пытаюсь добавить автопрокрутку в приложение в стиле чата и сталкиваюсь с этой проблемой: DynamicSizeList does not support scrolling to items that have not yet measured. scrollToItem() was called with index 111 but the last measured item was 110.

Я пытаюсь позвонить на scrollToItem(items.length-1) через componentDidUpdate

Это предполагаемое поведение?

Да, может что-то подобное сработает @piecyk 👍

Это предполагаемое поведение?

Не похоже на @xaviergmail , нет. Может ошибка.

эй @bvaughn Я не хочу сорвать эту проблему, но я хотел вмешаться, чтобы сказать, что есть аккуратная реализация разреженного массива из внутренних компонентов Flex 4 DataGrid, которая может помочь здесь. Я знаю, что Flash - это: -1 :, но последняя версия Flex на самом деле имела довольно хороший движок виртуализированной компоновки ... потому что Flash :-)

LinearLayoutVector - это разреженный массив для сопоставления индексов элементов и позиций пикселей в одном измерении. Три основных операции:

interface LinearLayoutVector {
   start: (index) => position;
     end: (index) => position;
  indexOf: (position) => index;
}

Внутри он распределяет корзины с степенями 2 для хранения позиций элементов (удельную мощность можно настроить для лучшего соответствия большим или меньшим размерам элементов). Это обеспечивает поиск в постоянном времени O (1) index -> position и эффективное линейное сканирование блоков для поиска position -> index . Он поддерживает заполнение, пробелы, размеры по умолчанию, а также вставку, удаление и обновление с произвольным доступом.

Я перенес его на JS около 6 лет назад, когда я делал много виртуализированных пользовательских интерфейсов для мобильных устройств. Он мог бы использовать обновление ES6 для удобства чтения и, вероятно, мог бы выжать больше скорости, переключившись на типизированные массивы, но основная логика разумна.

Несколько недель назад я отправил черновик PR для виртуализации реакции, который заменил внутренние компоненты CellSizeAndPositionManager на LLV, и это действительно решило несколько проблем, связанных с недействительностью перфоманса / кеша. Если вы упадете, я буду счастлив отправить аналогичный PR на react-window в следующие несколько недель.

Привет @trxcllnt 👋

Если вам интересно поделиться PR, я буду рад взглянуть. Вы бы хотели сделать это против ветки issues/6 (WIP PR # 102).

На первый взгляд, linear-layout-vector не выглядит так, как будто у него есть какие-либо тесты или он слишком интенсивно используется, поэтому у меня было бы немного первоначального сопротивления, но я все равно хотел бы взглянуть. Я также хотел бы посмотреть, какой вес он добавляет к бандлу после того, как его убрали + уменьшили, но я бы не ожидал, что он добавит слишком много. 😄

@bvaughn не

После того, как я прокомментировал, я вспомнил, что у меня есть демо, для которого я сделал порт: https://github.com/trxcllnt/virt-list. Зайдите на этот сайт GH Pages и пролистайте список фильмов влево и вправо (это было связано с некоторыми обсуждениями производительности рендеринга, которые мы вели в команде iOS в Netflix).

@bvaughn Спасибо за всю работу, проделанную в ветке issues / 6 за последний год!
В настоящее время я тестирую ^1.6.0-alpha.1 и планирую начать производство с этой версией.

Подумал, что опубликую, что мне нужно сделать, чтобы работать с новым DynamicSizeList для всех, кто смотрит на эту проблему и использует последнюю версию в ветке.

Следуя приведенным выше документам и документам, созданным из ветки issues / 6, вы получите

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

и поэтому исправление заключалось в имитации того, что вы делаете в тестах и ...

import { DynamicSizeList as List } from 'react-window';
import AutoSizer from 'react-virtualized-auto-sizer';

// in constructor(props) for handling scrolling
this.listRef = React.createRef();

// in render()
const allItems = [...];
const Renderer = ({ forwardedRef, style, index, ...rest }) => (
  <div ref={forwardedRef} style={style}>
    <MyCoolComponent index={index} otherProps={otherPropsBasedOnAllItems} />
  </div>
);

const RefForwarder = React.forwardRef((props, ref) => (
  <Renderer forwardedRef={ref} {...props} />
));

return <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
  <div style={{ flexGrow: 0, flexShrink: 0, width: '100%', position: 'sticky', top: 0, zIndex: zIndexHideLayers }}>
    <MyCoolComponentThatControlsScrolling listRef={this.listRef} />
  </div>
  <div style={{ flex: 1, width: '100%' }}>
    <AutoSizer>
      {({ height, width }) => (
        <List ref={this.listRef} itemCount={allItems.length} width={width} height={height}>
          {RefForwarder}
        </List>
      )}
    </AutoSizer>
  </div>
</div>;

Мой пример, вероятно, включает в себя больше, чем вы хотели бы на этой странице документов, но, надеюсь, упростит вам обновление документа.

Отзыв о текущей версии ветки?
💯 хорошо работает
🎉 еще раз спасибо за всю работу!

edit: DynamicSizeList серьезно делает эту библиотеку теперь такой простой в использовании.

Спасибо, что поделились подробностями! Когда я получу некоторую пропускную способность, чтобы снова решить эту проблему, я раскрою их.

Я думаю, что этот подход можно использовать вместе с исходным предложением в этом выпуске.

Вместо того, чтобы использовать предыдущий размер элемента, мы могли бы просто использовать приблизительные размеры - и уточнять фактические размеры, когда кто-то прокручивает. (Я не думаю, что есть важное различие между «ранее измеренным размером» и «предполагаемым размером», за исключением того факта, что ранее измеренный размер, вероятно, будет более точным. Тем не менее, это может быть приемлемым компромиссом, поскольку он позволит переходить к произвольным местам в данных без рендеринга вещей, которые были раньше, _и_ это освободило бы нас от необходимости поддерживать кеш размера элементов.)

Я думаю, что это могло бы значительно упростить проблему привязки прокрутки. Мы могли бы просто сделать начальный прыжок (как описано), а затем притвориться, что все «до» (вверху или слева) было точно предполагаемого размера. Затем по мере прокрутки уточняйте.

Может может работать?

@bvaughn Исправит ли это проблему, которую решила @xaviergmail , с первоначальной прокруткой вниз, как в чате? Я создал код и пример того, что он не работает. Если нет, есть ли обходные пути?

https://codesandbox.io/s/vr648ywy3

Давайте оставим комментарии по этой проблеме, сфокусированные на обсуждении API, а не на устранении неполадок.

Я предлагаю Stack Overflow, чтобы задавать вопросы.

Можно ли в этом API выставить resetAfterIndex? Я добавляю, редактирую и удаляю из своего списка DynamicSizeList, и, по крайней мере, из того, что я могу собрать, это был бы метод, который нужно вызвать, чтобы исправить высоту, да?

@bvaughn на выходных

реализация poc https://github.com/piecyk/react-window/pull/2/files
вот песочница кода, запускающая сборку ветки
https://codesandbox.io/s/4x1q1n6nn9

э-э, firefox не успевает за рендерингом при быстрой прокрутке, как это делает хром, используя этот подход 🤷‍♂️

Я пытаюсь добавить автопрокрутку в приложение в стиле чата и сталкиваюсь с этой проблемой: DynamicSizeList does not support scrolling to items that have not yet measured. scrollToItem() was called with index 111 but the last measured item was 110.

Я пытаюсь позвонить на scrollToItem(items.length-1) через componentDidUpdate

Это предполагаемое поведение?

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

Не лучшее решение, но я все еще над ним работаю. Может быть, мы сможем сделать его более общим (и простым) и создать пакет?

Gif, чтобы показать, как это работает прямо сейчас:
https://cl.ly/87ca5ac94deb

Может быть, мы сможем открыть новый выпуск, чтобы обсудить решение этой проблемы, подобной чату?

э-э-э, firefox не успевает за рендерингом при быстрой прокрутке, как Chrome, используя этот подход

Похоже, это работает в Firefox Nightly версии 68.

@bvaughn Я использую DynamicSizeList с компонентами InfiniteLoader и Autosizer, чтобы попытаться создать канал. Мне нравится то, что я видел, так держать :)

Что касается API и поведения:

  1. Можем ли мы получить объект данных в качестве второго аргумента в обратном вызове itemKey, как в FixedSizeList?

  2. Можем ли мы сбросить высоту внутреннего контейнера, когда объект данных фильтруется / изменяется.

Я уже некоторое время использую DynamicSizeList из 1.6.0-alpha.1 с InfiniteLoader и он отлично работает. Спасибо за отличную функцию!

Однако теперь у меня есть требование использовать scrollToItem() . Подобно предыдущему комментарию, но отчетливо, потому что еще ничего не измерено, я получаю:

DynamicSizeList does not support scrolling to items that yave not yet measured. scrollToItem() was called with index 9 but the last measured item was -1.

Кажется, это не связано со временем, поскольку я пытался позвонить после длинного setTimeout . Итак, могу ли я принудительно провести измерение? Или есть какие-то обходные пути?

РЕДАКТИРОВАТЬ : Неважно, initialScrollOffset сделал то, что мне нужно.

зачем использовать findDOMNode?

Существуют ли определения типов для ветви @next ?

@WillSquire нет, они этого не делают. Я также не уверен, можно ли выпустить их в теге @next в DefinentyTyped (я могу ошибаться). Кроме того, я думаю, что было бы лучше подождать, пока эта ветка наконец не будет объединена и выпущена новая версия, поскольку API все еще может измениться.

@bvaughn Я был готов использовать это на devhub , но прежде чем я вкладываюсь в его интеграцию, вы думаете, что он уже в хорошей форме или все еще имеет некоторые проблемы с блокировкой?

@brunolemos Я дел на # 102 довольно точен. Если вы протестировали и чувствуете, что он в хорошей форме для браузеров, на которые вы нацеливаетесь, держите меня в курсе!

держи меня в курсе!

~ Пытался использовать, но пока безуспешно. ~

Получил, что работает, но производительность не очень хорошая. Может быть, рендеры моих предметов дорогие или что-то еще.

https://github.com/devhubapp/devhub/pull/152

Похоже, что что-то могло сломаться в последней версии при использовании AutoSizer с высотой контейнера 100%.

Изменить: мне удалось найти обходной путь, используя 100vh и calc ()

что-то могло сломаться

Слишком расплывчато, чтобы действовать. Поделитесь репликой с ожидаемым поведением?

Я использую DynamicSizeList из 1.6.0-alpha.1 с разными фильтрами и сложным представлением карточек. Но нам нужно обернуть по высоте и ширине. У меня все работает нормально.

Спасибо вам, ребята

Здравствуйте, я пробую DynamicSizeList , но все мои элементы отображаются друг на друге. Я передаю атрибут стиля визуализированному элементу, но если я регистрирую style , я вижу, что height не определено для каждого элемента, top и left всегда 0 .
Что я здесь пропустил :-)?

@ graphee-gabriel вы упускаете пример воспроизведения.

Первоначально высота намеренно не указана, чтобы элементы отображались с их естественным размером ...

Хорошо, я понимаю логику, тогда это не причина, по которой элементы отображаются друг на друге.
Я предоставлю столько данных, сколько смогу. Я подумал, что, возможно, я совершил типичную ошибку или пропустил очевидный шаг, который приводит к этой проблеме (например, не передать объект стиля).

Screen Shot 2019-07-07 at 18 08 53

import React from 'react'
import { DynamicSizeList as List } from 'react-window'

import Layout from '../Layout'
import Text from '../Text'
import withScreenDimensions from '../withScreenDimensions'

class ListView extends React.Component {
  state = {
    availableHeight: 0
  }

  componentDidMount() {
    const checkForHeightChange = () => {
      if (this.containerDiv) {
        const { offsetHeight } = this.containerDiv
        if (this.offsetHeight !== offsetHeight) {
          this.offsetHeight = offsetHeight
          this.setState({ availableHeight: offsetHeight })
        }
      }
    }
    checkForHeightChange()
    this.intervalId = setInterval(checkForHeightChange, 10)
  }

  componentWillUnmount() {
    clearInterval(this.intervalId)
  }

  render() {
    const {
      data,
      renderItem,
      emptyText,
      dimensions,
    } = this.props
    const { width } = dimensions
    const { availableHeight } = this.state
    return (
      <Layout
        centerVertical
        style={{
          height: '100%',
        }}>
        {data && data.length > 0 ? (
          <div
            style={{
              display: 'flex',
              flex: 1,
              height: '100%',
              backgroundColor: 'red',
              alignItems: 'stretch',
              justifyContent: 'stretch',
            }}
            ref={ref => this.containerDiv = ref}
          >
            <List
              height={availableHeight}
              itemCount={data.length}
              width={width > 800 ? 800 : width}
            >
              {({ index, style }) => {
                console.log('style', style)
                return (
                  <div style={style}>
                    {renderItem({
                      item: data[index], index
                    })}
                  </div>
                )
              }}
            </List>
          </div>
        ) : (
            <Text bold center padding accent>{emptyText}</Text>
          )}
      </Layout>
    )
  }
}


export default withScreenDimensions(ListView)

Поделиться песочницей кода, где я могу это увидеть?

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

@graphee-gabriel У меня тоже было это, в документации об этом не упоминается, но вам нужно, чтобы ваш компонент строки поддерживал получение ссылки:

Row = React.forwardRef(
      (row, ref) => (
        <div ref={ref} style={row.style}>
          {renderItem({
            item: data[row.index],
            index: row.index,
          })}
        </div>
      ),
    )

Привет, вот и все:

https://codesandbox.io/s/sweet-sea-irxl8?fontsize=14

Да, действительно, для встроенных функций, это действительно старый код, который я пытался перенести на response-window, и не нашел времени, чтобы улучшить его и здесь.
Спасибо за ваш отзыв. Сообщите мне, что вы найдете в этой песочнице.

Анннннд, я должен был проверить сообщение @brunolemos, прежде чем делать эту песочницу, хе-хе.
Это был пропущенный шаг, и моя проблема была решена, спасибо!

Это вызвало еще одну проблему, я обновил песочницу, чтобы вы могли воспроизвести @bvaughn
Найдите здесь: https://codesandbox.io/s/sweet-sea-irxl8

Теперь список работает нормально, но, как ни странно, кажется, что он растет вместе с содержимым и больше никогда не сжимается.

Имея в виду:

  1. Если я показываю 6 пунктов, прокручиваю до конца, все нормально.
  2. Измените содержимое, чтобы отобразить 20 элементов, прокрутите до конца, все в порядке.
  3. Измените содержимое до 6 элементов, прокрутите до последнего элемента, но я могу продолжить прокрутку на пустом пространстве, которое, кажется, осталось от предыдущего содержимого (набор данных из 20 элементов).

Это вызвало еще одну проблему, я обновил песочницу, чтобы вы могли воспроизвести @bvaughn
Найдите здесь: https://codesandbox.io/s/sweet-sea-irxl8

Теперь список работает нормально, но, как ни странно, кажется, что он растет вместе с содержимым и больше никогда не сжимается.

Имея в виду:

  1. Если я показываю 6 пунктов, прокручиваю до конца, все нормально.
  2. Измените содержимое, чтобы отобразить 20 элементов, прокрутите до конца, все в порядке.
  3. Измените содержимое до 6 элементов, прокрутите до последнего элемента, но я могу продолжить прокрутку на пустом пространстве, которое, кажется, осталось от предыдущего содержимого (набор данных из 20 элементов).

У меня такая же проблема

Это именно то, что мне было нужно.
Я только что протестировал DynamicSizeList из 1.6.0-alpha.1 в сочетании с react-virtualized-auto-sizer и react-window-infinite-loader с очень хорошими результатами.
Чем я могу помочь, чтобы продвинуться вперед?

Привет @bvaughn , у тебя было время проверить коды и ящик с https://github.com/bvaughn/react-window/issues/6#issuecomment -509213284?

Привет, я использую DynamicSizeList для своего приложения для чата.
Спасибо за потрясающую функцию.

Однако у меня проблемы с низкой производительностью и большим объемом обработки скриптов.
При прокрутке CPU всегда поднимается и часто достигает 100%.
Есть ли у вас идеи решений?

import { useChatList } from '../../../hooks/chat/useChatList';
import LoadingSpinner from '../../../utils/LoadingSpinner';

import dynamic from 'next/dynamic';
import * as React from 'react';
import AutoSizer from 'react-virtualized-auto-sizer';
// @ts-ignore
import { DynamicSizeList as List } from 'react-window';
import { Message } from 'src/app/typings';

const { useRef, useCallback } = React;

const RowItem = React.memo(
  ({ forwardedRef, style, index, data }: any) => {
    const item = data[index] as Message;
    if (item) {
      return (
        <div id={item.messageId} ref={forwardedRef} style={style}>
          {item.text && item.text.plainText}
        </div>
      );
    }
    return null;
  },
  (prevProps, newProps) => {
    const { index, data } = prevProps;
    const { index: newIndex, data: newData } = newProps;
    let isMemo = true;
    isMemo = isMemo && index === newIndex;
    isMemo = isMemo && data.length === newData.length;
    return isMemo;
  }
);

function ChatList() {
  const listRef = useRef<HTMLInputElement>();

  const { formatMessages: messages, isLoadingMessages } = useChatList();

  const keyCreator = useCallback((index: number) => `ChatList/RowItem/${messages[index].messageId}`, [messages]);

  if (isLoadingMessages && (!messages || messages.length <= 0)) {
    return <LoadingSpinner />;
  }
  return (
    <div style={{ flex: 1, height: '100%', width: '100%' }}>
      <AutoSizer>
        {({ height, width }) => (
          <List
            ref={(lref: HTMLInputElement) => {
              if (lref !== null) {
                listRef.current = lref;
              }
            }}
            itemCount={messages.length}
            itemData={messages}
            itemKey={keyCreator}
            height={height}
            width={width}
            overscanCount={10}
          >
            {React.forwardRef((props, ref) => (
              <RowItem forwardedRef={ref} {...props} />
            ))}
          </List>
        )}
      </AutoSizer>
    </div>
  );
}

export default ChatList;

スクリーンショット 2019-07-14 11 49 54

Привет @bvaughn ,
Как правильно пересчитать высоту элементов при изменении размера рабочего места? С помощью комментариев выше я делаю демо https://codesandbox.io/s/angry-hill-tcy2m
При изменении ширины рабочего места с помощью мыши мне нужно пересчитать высоту всего элемента (и, возможно, очистить внутренний кеш высоты компонента VariableSizeList) ...

есть ли сейчас какое-либо решение для динамического списка, я просто потратил 4 часа, пытаясь заставить его работать, да
после прочтения всех комментариев я закончил 😠
Если у вас есть рабочее решение, пожалуйста, предоставьте мне

В этом проекте нет «вы, ребята». Его обслуживает один человек.

И довольно невнимательно оставлять в один день комментарии по нескольким вопросам, жалуясь на одно и то же. Во что бы то ни стало, просто используйте react-virtualized.

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

@ShivamJoker Я почти заставил его работать, единственное, что осталось, чтобы он работал идеально, - это общая высота, которая продолжает расти, но никогда не уменьшается после изменения содержимого на меньшее количество элементов. Если это будет решено, в моем случае, похоже, он сработает отлично.

@bvaughn , у вас будет время проверить пример в песочнице с https://github.com/bvaughn/react-window/issues/6#issuecomment -509213284?

=> https://codesandbox.io/s/sweet-sea-irxl8

Он начинается с более короткого списка, поэтому:

  • прокрутите вниз до конца списка
  • прокрутите назад и нажмите Show Long List
  • прокрутите вниз до конца
  • прокрутите назад и нажмите Show Short List
  • Наконец, прокрутите вниз в последний раз, чтобы увидеть, что за коротким списком теперь стоит много пробелов.

Спасибо!

@ShivamJoker Я почти заставил его работать, единственное, что осталось, чтобы он работал идеально, - это общая высота, которая продолжает расти, но никогда не уменьшается после изменения содержимого на меньшее количество элементов. Если это будет решено, в моем случае, похоже, он сработает отлично.

@bvaughn, успеешь ли ты проверить пример в песочнице из №6 (комментарий) ?

=> https://codesandbox.io/s/sweet-sea-irxl8

Он начинается с более короткого списка, поэтому:

  • прокрутите вниз до конца списка
  • прокрутите назад и нажмите Show Long List
  • прокрутите вниз до конца
  • прокрутите назад и нажмите Show Short List
  • Наконец, прокрутите вниз в последний раз, чтобы увидеть, что за коротким списком теперь стоит много пробелов.

Спасибо!

Да, в основном внутренний контейнер должен сбрасывать высоту после фильтрации / изменения данных.

@ShivamJoker Я почти заставил его работать, единственное, что осталось, чтобы он работал идеально, - это общая высота, которая продолжает расти, но никогда не уменьшается после изменения содержимого на меньшее количество элементов. Если это будет решено, в моем случае, похоже, он сработает отлично.

@bvaughn, успеешь ли ты проверить пример в песочнице из №6 (комментарий) ?

=> https://codesandbox.io/s/sweet-sea-irxl8

Он начинается с более короткого списка, поэтому:

  • прокрутите вниз до конца списка
  • прокрутите назад и нажмите Show Long List
  • прокрутите вниз до конца
  • прокрутите назад и нажмите Show Short List
  • Наконец, прокрутите вниз в последний раз, чтобы увидеть, что за коротким списком теперь стоит много пробелов.

Спасибо!

спасибо, я реализовал то же самое, надеясь, что он будет работать нормально и для других пользователей
и да, я также видел, что проблема с высотой прокрутки

@graphee-gabriel, но у меня есть еще одна проблема, которую моя панель приложения использовалась для скрытия при прокрутке вниз, чего сейчас не происходит, что может быть решением?
image

Добрый день. Я использовал DinamycSizeList в своем демонстрационном проекте. Все было хорошо, но через некоторое время я заметил, что компонент списка стал работать некорректно. Сначала я подумал, что это какая-то библиотека, от которой зависит response-window. Но глядя на вашу демонстрацию
https://react-window-next.now.sh/#/examples/list/dynamic -size
заметил примерно такой же результат, хотя раньше тоже работал отлично. Не могли бы вы подсказать причину этих ошибок?

@simeonoff

Да, в основном внутренний контейнер должен сбрасывать высоту после фильтрации / изменения данных.

Как мне это сделать? Я попытался установить высоту состояния, но, похоже, это не работает
любое решение?

@simeonoff

Да, в основном внутренний контейнер должен сбрасывать высоту после фильтрации / изменения данных.

Как мне это сделать? Я попытался установить высоту состояния, но, похоже, это не работает
любое решение?

Это должно быть реализовано внутри библиотеки.

@ShivamJoker Я почти заставил его работать, единственное, что осталось, чтобы он работал идеально, - это общая высота, которая продолжает расти, но никогда не уменьшается после изменения содержимого на меньшее количество элементов. Если это будет решено, в моем случае, похоже, он сработает отлично.

@bvaughn, успеешь ли ты проверить пример в песочнице из №6 (комментарий) ?

=> https://codesandbox.io/s/sweet-sea-irxl8

Он начинается с более короткого списка, поэтому:

  • прокрутите вниз до конца списка
  • прокрутите назад и нажмите Show Long List
  • прокрутите вниз до конца
  • прокрутите назад и нажмите Show Short List
  • Наконец, прокрутите вниз в последний раз, чтобы увидеть, что за коротким списком теперь стоит много пробелов.

Спасибо!

Вы можете установить ключ для предотвращения пробелов.
https://codesandbox.io/s/blissful-voice-mzjsc

Привет, @bvaughn, спасибо за этот потрясающий проект!

Из-за необходимости я провел довольно много времени в коде DynamicLists, пытаясь выяснить, как прокручивать в любом месте без каких-либо ограничений и как прокручивать до любого элемента, измеренного и нет.

Мне удалось это сделать здесь https://github.com/bvaughn/react-window/compare/issues/6...Sauco82 : issues / 6, избавившись от lastMeasuredIndex и вместо этого проверяя каждый элемент с помощью itemIsMeasured , что, очевидно, в свою очередь требует многих других изменений.

Я никогда не участвовал в проектах с открытым исходным кодом и не использовал Flow, поэтому я не совсем уверен, полезно ли это или стоит ли включать их, а также стоит ли мне напрямую пробовать PR или обсуждать это здесь.

Я рад помочь и настроить, поэтому, если вам что-нибудь понадобится, дайте мне знать.

Эй, вот гораздо более простое решение (не нужно добавлять элементы-призраки в DOM для расчета их размера):
Коды

Эй, вот гораздо более простое решение (не нужно добавлять элементы-призраки в DOM для расчета их размера):
Коды

Потрясающие! Меня устраивает. Хорошая работа.

@Kashkovsky рассчитал размер, если был обновлен
и itemSize вызывается один раз

@ userbq201 @Kashkovsky отличное решение! Как-то в моем случае из коробки не вышло, пришлось модифицировать код ChatHistory.js вот так:

    const listRef = useRef(); // added
    const sizeMap = useRef({});
    const setSize = useCallback((index, size) => {
        sizeMap.current = {...sizeMap.current, [index]: size};
        listRef.current.resetAfterIndex(index); // added
    }, []);
    const getSize = useCallback(index => sizeMap.current[index] || 60, []);
    // ...
    <List ref={listRef}

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

@bvaughn что, если нам нужно включить аналогичное поведение для SSR? есть намек на эту сторону?

@bvaughn Это я или твоя демка не работает?

Хорошая реализация @Kashkovsky @ kirill-konshin и @ userbq201 !

Как бы вы подошли к использованию мемоизации с этим решением?

Я попытался заключить ChatMessage в memo с areEqual , но React по-прежнему повторно отображает каждый объект каждый раз, когда сообщение добавляется в список.

В других моих списках FixedSizedLists мемоизация отлично работает с этой оболочкой memo / areEqual, но, возможно, на нее влияет ref={root} ?

Вы можете легко определить, выполняет ли React повторный рендеринг компонентов, вставив

Я раздвоил пример здесь: https://codesandbox.io/s/dynamic-size-of-react-window-list-items-nb038


РЕДАКТИРОВАТЬ: я исправил мемоизацию - он предназначен для обертывания начального функционального компонента с помощью памятки, а не как я это сделал. Вот мемоизированное решение на случай, если у кого-то есть сложная структура DOM внутри своих списков (или если им нужно отображать видео, как я): https://codesandbox.io/s/dynamic-size-of-react-window-list -items-errt4


РЕДАКТИРОВАТЬ 2: Оказывается, первоначальный рендеринг строк в порядке, но вызовом resetAfterIndex очень сложно управлять. Мои данные меняются (например, когда пользователь выбирает другой разговор). Но настоящая проблема в том, что resetAfterIndex кажется, запускается до того, как завершится новый setSize . Таким образом, он успешно очищает кешированный стиль, но затем он просто снова создает новый кеш старых стилей, потому что браузер не завершил изменение размера содержимого.

Не уверен, что это имеет смысл при написании, но пока я должен вставить булавку в это. Пожалуйста, дайте мне знать, успешно ли кто-нибудь динамически меняет свой контент и поддерживает обновленные стили высоты.

У меня есть много других реализаций окна реакции, поэтому я бы предпочел найти здесь хорошее решение вместо использования реакции-виртуализации для этого одного варианта использования.


РЕДАКТИРОВАТЬ 3: это будет моя последняя редакция, так как я, наконец, придумал полу-элегантное решение.

1.) Если itemData нужно изменить (например, при изменении разговора), размонтируйте весь компонент, а затем повторно смонтируйте его с новым itemData. Это можно сделать с помощью обратного вызова setState. Это гарантирует, что старые стили высоты не будут перенесены при изменении данных.

2.) Я передал {sizeMap, setSize, listRef} ChatMessage через ChatContext . Таким образом, вместо того, чтобы просто устанавливать размер вслепую, я могу сказать ChatMessage установить размер И сравнить его со старым размером. Если старый размер отличается от нового размера, вызовите resetAfterIndex начиная с index и передав значение true для принудительного обновления.

Итак, мое новое сообщение ChatMessage выглядит примерно так:

const ChatMessage = ({ message, index }) => {
    const { setSize, sizeMap, listRef } = useContext(ChatContext);
    const root = React.useRef();
    useEffect(() => {
        let oldSize = sizeMap[index];
        let newSize = root.current.getBoundingClientRect().height;
        setSize(index, newSize);
        if(newSize !== oldSize){
            listRef.current.resetAfterIndex(index,true);
        }
    }, [sizeMap, setSize, listRef]);

    return (
        <div ref={root}
             {message.body}
        </div>
    );
};
export default ChatMessage;

3.) Я добавил то, что по сути является слушателем в компонент, который ждет только что смонтированного для рендеринга. После рендеринга он прокручивается вниз. Это устраняет проблему с попыткой поместить функцию scrollTo непосредственно в componentDidMount, поскольку она никогда не отображалась до вызова этого метода. Так выглядит так:

class Chat extends Component {
    constructor(props) {
        super(props);
        this.listRef = createRef();
        this.state = {
            initialScrollComplete: false,
            interval: null
        };
    }

    componentDidMount(){
        // Create interval to check if list is ready. Once ready, scroll to bottom of list.
        this.setState({interval: setInterval(()=>{
            if(this.listRef.current && !this.state.initialScrollComplete){
                this.listRef.current.scrollToItem(this.props.chatHistory.length - 1, "end");
                this.setState({initialScrollComplete: true});
            }
        },25)});
    }

    componentDidUpdate(prevProps, prevState) {

        // Clear interval if scroll has been completed
        if(!prevState.initialScrollComplete && this.state.initialScrollComplete){
            clearInterval(this.state.interval);
            this.setState({interval: null});
        }

        // If new message is transmitted, scroll to bottom
        if(prevProps.chatHistory && this.props.chatHistory && prevProps.chatHistory.length !== this.props.chatHistory.length){
            this.listRef.current.scrollToItem(this.props.chatHistory.length - 1, "end");
        }

    }

    render() {
        return <ChatHistory listRef={this.listRef} chatHistory={this.props.chatHistory}/>;
    }
}

Кажется, на сафари действительно странное поведение.

Высота div DynamicSizedList и высота или верхняя граница строк работают неправильно, содержимое начинает перекрываться.

При изменении ширины окна / содержимого строки новая высота не пересчитывается и не изменяется для работы с новой высотой содержимого.

Что-то, кажется, исправляет это, если содержимое прокручивается, прокрутка до точки, где строка больше не видна, прокрутка назад до нее делает ее правильной.

Контент отображается некорректно при загрузке первой страницы, поэтому обновление, похоже, не решает проблему: /

Все это отлично работает в других браузерах, включая Chrome и Firefox. Safari - это ужасно, но, к сожалению, приложение все еще должно работать для людей, которые его используют.

Screenshot 2020-02-15 at 14 27 19

Мне действительно нужна помощь!

@tastyqbit Я также столкнулся с той же проблемой в Safari и Internet Explorer. Как вы упомянули, прокрутка мимо развернутой строки с последующей прокруткой назад позволяет ей правильно отображаться, но, конечно, это не решает проблему.

Если вы найдете обходные пути, дайте мне знать!

@afreix @tastyqbit Я MDN .

Я думаю, что отсутствие ResizeObserver должно вызывать предупреждение в консоли.

А что насчет такого https://codesandbox.io/s/agitated-jennings-o9nn6 ?

базовое использование VariableSizeList + ItemMeasurer из # 102 Я знаю, что это очень наивный подход, но похоже, что он вроде работает (не так уж плохо 😂) в качестве временного решения 🤔

В нашей команде мы столкнулись с необходимостью визуализировать большой список текстовых данных произвольного размера.
Для нас возможность точно переключаться между элементами и прокручивать без каких-либо задержек была обязательной.
После небольшого количества поисков в Интернете я сдался и написал эту библиотеку .
Надеюсь, это поможет некоторым из вас в качестве временного решения: smile_cat:

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

@ gnir-work что, если размер окна изменится и размер контейнера изменится, что приведет к изменению размера списка?

Читая эту ветку, я думаю, что может быть лучший способ обрабатывать элементы, ширина которых может меняться.

Определение «переменной» здесь варьируется по всему набору. Фактический размер элементов статический, а не динамический. Может быть, динамический - лучший термин, потому что размер может измениться во время изменения размера или мутации, если текст изменяется.

Это может сработать, если вы слушаете прокрутку родительского объекта.

Алгоритм будет работать так:

  • вычислить приблизительный размер для каждого элемента - это должно быть очень эффективно. Это не обязательно должно быть идеально. + - 20% в порядке.

  • мы визуализируем только видимые элементы + скажем, на 20% больше, чтобы, если пользователь прокручивает, он не видит никаких изменений

  • У нас есть «призрак» для всего остального, у которого «высота» установлена ​​на расчетную высоту. Это просто пустой div. Таким образом, полоса прокрутки будет выглядеть примерно вправо.

  • Элемент отображается только тогда, когда он находится в области просмотра. Кроме этого показаны призрачные предметы.

Единственным недостатком этого является то, что высота полосы прокрутки немного изменится. Я не уверен, что это отвлекает пользователя. Может быть, если список прокрутки большой. Мы МОЖЕМ быть в состоянии обмануть это, увеличив / уменьшив буфер таким образом, чтобы предполагаемые размеры не влияли на длину полосы прокрутки.

@ gnir-work что, если размер окна изменится и размер контейнера изменится, что приведет к изменению размера списка?

Начиная с последней версии ( 2.2.0 ) компонент поддерживает изменение размера всего списка (высоты и ширины).

Читая эту ветку, я думаю, что может быть лучший способ обрабатывать элементы, ширина которых может меняться.

Определение «переменной» здесь варьируется по всему набору. Фактический размер элементов статический, а не динамический. Может быть, динамический - лучший термин, потому что размер может измениться во время изменения размера или мутации, если текст изменяется.

Это может сработать, если вы слушаете прокрутку родительского объекта.

Алгоритм будет работать так:

  • вычислить приблизительный размер для каждого элемента - это должно быть очень эффективно. Это не обязательно должно быть идеально. + - 20% в порядке.
  • мы визуализируем только видимые элементы + скажем, на 20% больше, чтобы, если пользователь прокручивает, он не видит никаких изменений
  • У нас есть «призрак» для всего остального, у которого «высота» установлена ​​на расчетную высоту. Это просто пустой div. Таким образом, полоса прокрутки будет выглядеть примерно вправо.
  • Элемент отображается только тогда, когда он находится в области просмотра. Кроме этого показаны призрачные предметы.

Единственным недостатком этого является то, что высота полосы прокрутки немного изменится. Я не уверен, что это отвлекает пользователя. Может быть, если список прокрутки большой. Мы МОЖЕМ быть в состоянии обмануть это, увеличив / уменьшив буфер таким образом, чтобы предполагаемые размеры не влияли на длину полосы прокрутки.

Это уже было реализовано @bvaughn в react-virtualized . Основным недостатком этого подхода является то, что переход к определенной строке не работает должным образом и создает визуальные ошибки при прокрутке вверх.

@ gnir-work а ... ладно ... может, я прерву свою работу и посмотрю на react-virtualized.

Я думаю, что вы правы с проблемами прокрутки вверх, но я думаю, что могу исправить это, указав «приблизительный размер», а затем преобразовать его в фактический размер после установки компонента.

... но другая проблема, конечно, связана с обработкой динамического контента. Если что-то обновит, высота компонента изменится.

Если предполагаемый размер точен, то он может работать. Например, я недавно реализовал виртуализированный список с динамической высотой с реакцией-виртуализацией, и он работал хорошо, пока предполагаемый размер был точным. В противном случае функция прокрутки до строки сломает мое приложение ☹

Отправлено из почты для Windows 10

От: Кевин Бертон
Отправлено: вторник, 14 апреля 2020 г., 23:07
Кому: bvaughn / response-window
Копия: Нир Геллер; Упомянуть
Тема: Re: [bvaughn / response-window] Поддержка содержания, измеряемого точно в срок (# 6)

@ gnir-work а ... ладно ... может, я прерву свою работу и посмотрю на react-virtualized.
Я думаю, что вы правы с проблемами прокрутки вверх, но я думаю, что могу исправить это, указав «приблизительный размер», а затем преобразовать его в фактический размер после установки компонента.
... но другая проблема, конечно, связана с обработкой динамического контента. Если что-то обновит, высота компонента изменится.
-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub или откажитесь от подписки.

-
Это письмо было проверено на вирусы антивирусной программой Avast.
https://www.avast.com/antivirus

@ gnir-work ах ... Я думаю, мне не нужна функция "прокрутка до строки" ... хотя, может быть, я ошибаюсь.

Что этого должно хватить для ваших нужд 😊

Отправлено из почты для Windows 10

От: Кевин Бертон
Отправлено: Вторник, 14 Апрель 2020 23:13
Кому: bvaughn / response-window
Копия: Нир Геллер; Упомянуть
Тема: Re: [bvaughn / response-window] Поддержка содержания, измеряемого точно в срок (# 6)

@ gnir-work ах ... Я думаю, мне не нужна функция "прокрутка до строки" ... хотя, может быть, я ошибаюсь.
-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub или откажитесь от подписки.

-
Это письмо было проверено на вирусы антивирусной программой Avast.
https://www.avast.com/antivirus

В качестве обходного пути, если:

  • высота вашей строки списка зависит только от внутреннего текста (плюс, возможно, некоторые элементы с определенными размерами)
  • и ваш список имеет фиксированную ширину

вы можете использовать CanvasRenderingContext2D.measureText () для вычисления высоты строки вместо рендеринга всего компонента: poop:

CodeSandbox

@bvaughn Есть ли планы по публикации новой альфа-версии на npm? У нас не было обновлений с 1.6.0-alpha.1 😕

@bvaughn есть обновления? будет ли это исправлено в последних версиях?

Для тех, кто хочет использовать Typescript с DynamicSizeList - расширение модуля может дать типы, необходимые для DynamicSizeList отработки определений Определенного Типа (обходной путь к моему запросу, опубликованному в этой ветке в прошлом году).

Добавьте в проект следующее:

import React, { Component } from 'react'

declare module 'react-window' {
  export type DynamicSizeListProps = Omit<FixedSizeListProps, 'itemSize' | 'scrollToItem'>
  export class DynamicSizeList extends Component<DynamicSizeListProps> {}
}

Затем импортируйте как обычно:

import {
  DynamicSizeList,
  DynamicSizeListProps,
} from 'react-window'

// use as normal...

@types/react-window сначала необходимо установить FixedSizeListProps .

Спасибо за typedef, собираюсь добавить их сейчас! Я использую DynamicSizeList в продукте уже больше года. В настоящее время основан на этой вилке: "@john-osullivan/react-window-dynamic-fork": "^1.9.0-alpha.1" (это самая последняя версия?). Я попытался переключиться на react-virtuoso из-за неуверенности в том, действительно ли это будет выпущено / когда оно действительно будет выпущено. Но нашел его менее производительным и застрял с этим.

@bvaughn, пора ли проложить коровью тропу и опубликовать это в npm? Может быть, просто переименован в ExperimentalDynamicSizeList если вы все еще беспокоитесь о том, что он не готов.

Привет ребята! Спасибо за вашу тяжелую работу и за эту замечательную библиотеку. Я очень жду этой функции! Однако я бы посоветовал добавить информацию об этой проблеме в README и документацию / примеры. Мне потребовалось некоторое время, чтобы понять, что динамический контент на самом деле не поддерживается библиотекой и полезен только для элементов с фиксированным / известным размером. Я считаю, что в README есть хороший раздел часто задаваемых вопросов, где это можно было бы добавить.

если вы ищете таблицу / сетку / дерево, это будет хорошим началом https://autodesk.github.io/react-base-table/examples/dynamic-row-heights , построенное на VariableSizeGrid

@ tony-scio, не могли бы вы поделиться рабочим кодом и ящиком для использования DynamicSizeList из 1.6.0-alpha.1 с InfiniteLoader? Спасибо, я был бы очень признателен.

Кто-нибудь получил это для работы с react-beautiful-dnd? Кажется, что перетаскивание заставляет предметы прыгать друг на друга.

Кто-нибудь получил это для работы с react-beautiful-dnd? Кажется, что перетаскивание заставляет предметы прыгать друг на друга.

я тоже буду ждать этого ответа: D

[ПОМОЩЬ]
По этой ссылке нет кода для показа:
динамический размер-список-вертикаль
и мне нужна эта способность.
БЛАГОДАРНОСТЬ

[ПОМОЩЬ]
По этой ссылке нет кода для показа:
динамический размер-список-вертикаль
и мне нужна эта способность.
БЛАГОДАРНОСТЬ

https://react-window-next.now.sh/#/examples/list/dynamic -size

Есть новости по этому поводу? Нам нужно что-то похожее, насколько мы можем (обычно их очень мало, но в некоторых случаях может быть много) для рендеринга большого адаптивного списка элементов сетки (их высота динамическая и будет меняться на мобильных устройствах в виде различных текстовых обтеканий и т. Д.). Я чувствую, что react-window изменит правила игры, если сможет справиться с этим вариантом использования. Если нет, то есть ли надежные альтернативы?

Есть новости по этому поводу? Нам нужно что-то похожее, насколько мы можем (обычно их очень мало, но в некоторых случаях может быть много) для рендеринга большого адаптивного списка элементов сетки (их высота динамическая и будет меняться на мобильных устройствах в виде различных текстовых обтеканий и т. Д.). Я чувствую, что react-window изменит правила игры, если сможет справиться с этим вариантом использования. Если нет, то есть ли надежные альтернативы?

@JavaJamie, поскольку вы специально просили альтернативы - библиотека react -virtuoso поставляется со встроенной поддержкой для измерения динамического контента. Отказ от ответственности: я являюсь его автором.

@JavaJamie, поскольку вы специально просили альтернативы - библиотека react -virtuoso поставляется со встроенной поддержкой для измерения динамического контента. Отказ от ответственности: я являюсь его автором.

React-virtuoso также вдвое превышает размер окна реакции. Всегда нужно помнить о размере зависимости.

https://bundlephobia.com/[email protected]
https://bundlephobia.com/[email protected]

Я принял тот факт, что у меня нет ни времени, ни энергии, чтобы завершить это усилие. Если кто-то захочет завершить начатую мной ветку, я буду рад вашей помощи. (См. Также выпуск № 302, чтобы узнать, как это вписывается в выпуск второй версии в виде новых компонентов List и Grid .)

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

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

Один из приемов состоит в том, что мы использовали «блоки», чтобы повысить производительность. Обычно мы берем каждую строку и фактически помещаем ее в родительский блок из примерно 25 элементов, а затем меняем местами, когда это необходимо.

@burtonator было бы очень полезно

Может ли кто-нибудь предоставить безошибочную реализацию response-select с DynamicSizeList?
Я не могу заставить его работать вместе.
На данный момент у меня 2 проблемы (извините за отсутствие скриншотов):

  1. У всех элементов есть style={position: absolute, left: 0, top: 0} что не позволяет мне использовать этот стиль, поскольку все параметры расположены друг над другом.
  2. Если я не использую опору стиля, список отображается хорошо, но когда я немного прокручиваю, часть списка с параметрами в нем сжимается, а общая высота остается неизменной. Таким образом, когда я прокручиваю, я получаю x пикселей фактических параметров и длину x пикселей пробела.

Не удалось найти ни одного рабочего примера из двух.
Замечу, что в Chrome я использую вилку 1.9.0.

Редактировать. Нашел ответ здесь выше, в разделе скрытых комментариев. https://github.com/bvaughn/react-window/issues/6#issuecomment -509016422

Одним из упрощений проблемы прокрутки было бы использование полосы прокрутки для указания индекса элемента в списке вместо позиции в пикселях, если прокрутка находится на расстоянии больше, чем примерно одна высота области просмотра. Вместо того, чтобы пытаться «прокрутить вниз» X пикселей, компонент просто отображает элементы по желаемому индексу. На полпути вниз отображается элемент с индексом N / 2, а внизу отображается элемент с индексом N-1.

Это позволит осуществлять прямую прокрутку ползунка до середины или конца списка без отставания ползунка прокрутки во время рендеринга и вычисления размеров компонента. Прямо сейчас для очень длинных компонентов VariableSizeList практически невозможно прокрутить вниз, поскольку курсор перемещается быстрее, чем движется ползунок прокрутки.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги