От автора: рендеринг большого набора данных в DOM без правильных инструментов может быть довольно затратным, так как это отрицательно сказывается на производительности веб-страницы; замедляет время выполнения, сетевые запросы и производительность памяти. В этом руководстве мы рассмотрим, как визуализировать большой объем данных из внешнего API или фиктивного файла данных в нашем приложении.
Мы будем использовать библиотеку React под названием response-window, для рендеринга большого количества данных. Затем мы создадим простое приложение для электронной коммерции, отображающее список продуктов.
Эта статья поможет веб-разработчикам создать лучшее веб-приложение, которое отображает и обрабатывает большие объемы данных в формате списка или сетки. В нем будут представлены и рассмотрены решения недостатков с бесконечной прокруткой или разбиением на страницы, предусмотренные при виртуализации данных. Также будут описаны лучшие практики UI / UX, необходимые при создании приложений, которые отображают большой объем данных.
Что такое виртуализация?
Виртуализация как техника прокрутки — это процесс рендеринга, который отслеживает положение прокрутки пользователя и визуально отображает только содержимое DOM в текущей позиции области просмотра. Этот метод включает обработку большого набора данных в шаблоне бесконечной прокрутки, но постепенную загрузку и рендеринг длинных списков данных в таком объеме, в каком данные поступают в область просмотра. Эта концепция предоставляет разработчикам все преимущества разбивки на страницы, в то же время обеспечивая преимущества UX, полученные от бесконечной прокрутки.
Использование виртуализации — распространенное решение, применяемое для рендеринга большого количества сообщений в приложениях социальных сетей, доставки больших новостных данных в приложениях СМИ, а также в бухгалтерском программном обеспечении. Бесконечная двухмерная прокрутка содержимого также включает в себя виртуальную прокрутку, которая помогает легко отображать постоянно меняющиеся местоположения позиции области просмотра при ее использовании. И виртуализация поддерживает отображение больших наборов данных в формате сетки или списка (в виде электронных таблиц).
Простая реализация виртуализации включает предварительное вычисление совокупной высоты списка данных с использованием API-интерфейса Intersection Observer, предоставляемого веб-API, и умножение его на общее количество элементов списка. Но в этом уроке мы воспользуемся другим более простым подходом — с помощью react-window.
React-window — это упрощенная версия пакета react-virtualized для простой реализации виртуализации в приложениях React через API (компоненты). Согласно документации, react-window работает только путем рендеринга части большого набора данных (ровно столько, чтобы заполнить область просмотра), что сокращает объем работы (и время), требуемой для рендеринга начального представления и обработки входящих обновлений в пользовательский интерфейс, а также также уменьшает объем выделяемой памяти.
Четыре компонента react-window
Давайте рассмотрим четыре доступных компонента, которые можно использовать для отображения списков элементов при использовании react-window в приложениях React.
FixedSizeList — этот компонент помогает отображать элементы фиксированного размера, определенные через свойство index. Общие доступные свойства, которые могут быть переданы этому компоненту: useIsScrolling, itemCount, itemSize, itemData, innerElementTypeи т.д.
VariableSizeList — этот компонент принимает то же, что и FixedSizeList, но с дополнительными свойствами, такими как estimatedItemSize и itemSize и возвращает размер элемента в направлении окна.
FixedSizeGrid — с помощью этого компонента мы выполняем рендеринг с использованием размеров: вертикального (столбцы) и горизонтального (строки) направлений. Другое отличие состоит в том, что нам нужно будет добавить количество данных. Общийе свойства rowCount, rowWidth, columnCount, columnWidth, height, width и т.д.
VariableSizeGrid — это компонент похожий на FixedSizeGrid с дополнительными свойствами: columnWidth и rowHeight, которые принимают функции в качестве значений этих свойств.
В этом руководстве мы сосредоточимся на использовании компонента FixedSizeList, который дает удобное для новичков введение в использование react-window в приложениях React (простое приложение электронной коммерции, отображающее список продуктов).
Реализация react-window в приложениях React
Давайте установим react-window используя yarn. В этом руководстве react-window будет установлен как зависимость, а типы для него будут установлены как devDependency. Также установим faker.js как зависимость:
yarn add react-window faker yarn add -D @types/react-window
После успешного завершения установки откройте файл ./src/App.js и добавьте следующую разметку JSX:
import { useState } from "react"; import * as faker from "faker"; const App = () => { const [data, setData] = useState(() => Array.from({ length: 1200 }, faker.commerce.product) ); return ( <main> <ul style={{ width: "400px", height: "700px", overflowY: "scroll" }}> {data.map((product, i) => ( <li key={i + product}>{product}</li> ))} </ul> </main> ); };
В приведенном выше коде мы определили структурную разметку для списка данных, отображаемых в DOM. Затем передали тегу ul свойство базового стиля, чтобы добавить стили фиксированной ширины и высоты, а также установить для scroll значение переполнения. Также мы будем использовать React хук useState, чтобы управлять нашим состоянием data, фиктивными данными предоставленными faker.js.Создадим массив размером 1200 и заполняем его достаточным количеством данных из faker.js.
Далее, начнем реализацию виртуализации с помощью компонента FixedSizeList. Этот компонент отвечает за рендеринг отдельного элемента фиксированного размера:
import { useState } from "react"; import * as faker from "faker"; import { FixedSizeList as List } from "react-window"; const App = () => { const [data, setData] = useState(() => Array.from({ length: 1200 }, faker.commerce.product) ); return ( <main> <List innerElementType="ul" itemData={data} itemCount={data.length} itemSize={20} height={700} width={400} > {({data, index, style }) => { return ( <li style={style}> {data[index]} </li> ); }} </List> </main> ); };
В элементе List используются два подхода к разметке, определяемые его свойствами, innerElementType и outerElementType. Их значения по умолчанию равны divs, но в нашем случае мы установим outerElementType значение ul. Затем мы передадим компоненту li в качестве дочернего элемента List, снабдив его необходимыми параметрами стилей (стилями абсолютного позиционирования и т. д.). Также передадим свойства width и height, которые мы ранее определили через style. Затем, используя itemCount, мы создаем воображаемый массив с той же длиной, что и data. Затем мы явно делаем data доступным для элементов li через свойство itemData.
Давайте изменим уникальное значение свойства key для элементов li, используя itemKey, доступное для компонента List. Мы будем использовать функцию faker.datatype.uuid для генерации случайного UUID и заполнения им itemKey.
... const App = () => { ... return ( <main> <List innerElementType="ul" itemData={data} itemCount={data.length} itemKey={faker.datatype.uuid} itemSize={20} height={700} width={400} > {({data, index, style }) => { return ( <li style={style}> {data[index]} </li> ); }} </List> </main> ); };
Этот код гарантирует, что мы используем списки React и ключевые передовые практики, как определено в документации. Термин «key» используется для описания специального строкового атрибута, который необходимо включить при создании списков элементов в приложениях React.
С помощью react-window мы можем пойти дальше, чтобы определить более структурированные элементы пользовательского интерфейса в дочерном свойстве, передаваемом в List, не влияя на оптимизированную производительность.
... const App = () => { const [data, setData] = useState(() => Array.from({ length: 1200 }, () => ({ productImg: faker.image.business(200, 600, true), product: faker.commerce.product(), productPrice: faker.commerce.price(2, 22, 1, "$"), productDescription: faker.commerce.productAdjective(), })) ); return ( <main> <List innerElementType="ul" itemData={data} itemCount={data.length} itemKey={faker.datatype.uuid} itemSize={20} height={700} width={400} > {({data, index, style }) => { return ( <li className="py-4 border-2 border-indigo-400 flex" {...props}> <img className="h-10 w-10 rounded-full" src={productImg} alt="" /> <div className="ml-3"> <p className="space-x-1"> <span className="text-base text-gray-900 whitespace-nowrap"> {product} </span> <span className="text-gray-600 text-base font-extrabold" style={{ backgroundImage: "linear-gradient(transparent 50%, pink 50%, pink 85%,transparent 85%,transparent 100%)", }} > {productPrice} </span> </p> <p className="text-sm text-gray-500">{productDescription}</p> </div> </li> ); }} </List> </main> ); };
Здесь мы обновили состояние нашего приложения, добавив больше полей данных, чтобы помочь смоделировать интернет-магазин, имеющий следующие атрибуты: изображение ( productImg), имя ( product), цена ( productPrice) и описание (productDescription) его продуктов. Мы также определили дополнительные элементы для хранения этих дополнительных данных.
(Примечание. Чтобы воспроизвести стили пользовательского интерфейса, использованные в этом руководстве, обязательно включите tailwind.css в файл /public/index.html.)
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" />
Если вы проверите компонент List из примера с помощью Devtools браузера, вы заметите, что независимо от того, насколько долго мы прокручиваем длинный список элементов в нашем приложении, количество элементов в его родительском div никогда не меняется. Что действительно изменится, так это то, насколько далеко каждый из них расположен от вершины.
Заключение
В этом руководстве мы обсудили, как использовать виртуализацию для оптимизации модели DOM при передачи в нее большого количества наборов данных. Затем был представлен react-window как пакет React, который эффективно реализует виртуализацию за капотом для рендеринга большого набора данных и в то же время ускоряет достижение целевых показателей производительности в нашем приложении. React-window делает это, отображая только те данные, которые находятся в области просмотра браузера. Cкачать код, использованный в этом руководстве, вы можете по ссылке на GitHub.
Автор: Ikeh Akinyemi
Источник: blog.openreplay.com
Редакция: Команда webformyself.
Читайте нас в Telegram, VK, Яндекс.Дзен