У вас есть пример использования этого с таблицами? Я пытаюсь заставить его работать, но у меня есть сильное подозрение, что он либо не работает, либо я делаю что-то очень не так.
Я установил для externalTagName значение «table», а для innerTagName значение «tbody», но прокрутки нет.
Вот мой код, не уверен, помогает ли он (items - это список объектов):
<List
outerRef={this._list}
outerTagName="table"
innerTagName="tbody"
height={300}
itemData={items}
itemSize={() => 30}
itemCount={items.length}
itemKey={item => item.uniqueId}>
{({index, style, data}) => {
return (
<tr style={style} key={index}>
<td>Item {index}</td>
</tr>
);
}}
</List>
Не думаю, что это действительно сработает. Насколько мне известно, HTMLTableElement
самом деле не поддерживает переполнение так, как это может потребоваться оконному компоненту. Вы _ можете_ изменить стиль на display: block
но я все еще не думаю, что это будет работать правильно. ( Вот пример .)
Зачем тебе стол? Я думаю, вы можете добиться того же макета столбцов с помощью встроенных блоков или гибких макетов.
Пара дополнительных вещей:
width
до List
key
в свои строкиitemSize
может быть просто 30
а не () => 30
(это будет работать немного лучше)Спасибо за быстрый ответ.
Мы уже обсуждали его переписывание в div, но поскольку это для существующего довольно большого компонента, мы просто хотели убедиться, прежде чем начинать это переписывание. Я видел некоторые другие комментарии о rc-table, поэтому подумал, что, возможно, это должно работать.
В любом случае, не возражайте против переписывания, я думаю, оно того стоит.
Я получил предупреждения React о ключах без ключа в строке, что также сбивало меня с толку, учитывая, что я устанавливаю itemKey, поэтому не уверен, что там происходит.
Спасибо
Эйнар
21 сентября 2018 года в 16:52 Брайан Вон [email protected] написал:
Не думаю, что это действительно сработает. Насколько мне известно, HTMLTableElement на самом деле не поддерживает переполнение в том смысле, в каком требуется оконный компонент. Вы можете изменить стиль на display: block, но я все равно не думаю, что это будет работать правильно.
Зачем тебе стол? Я думаю, вы можете добиться того же макета столбцов с помощью встроенных блоков или гибких макетов.
Пара дополнительных вещей:
Вы не указываете ширину обязательного параметра для списка
Вам не нужно добавлять ключ в свои строки
itemSize может быть просто 30, а не () => 30 (он будет работать немного лучше)
-
Вы получаете это, потому что вы являетесь автором темы.
Ответьте на это письмо напрямую, просмотрите его на GitHub или отключите чат.
Я получил предупреждения React о ключах без ключа в строке, что также сбивало меня с толку, учитывая, что я устанавливаю itemKey, поэтому не уверен, что там происходит.
Этого не ожидается. Можете ли вы поделиться со мной повторным случаем (через Code Sandbox)?
Ой, извини. Я должен добавить, что этого можно было бы _только_ ожидать, если бы ваша функция itemKey
вернула undefined
для некоторых элементов - и в этом случае исправление должно быть связано с этой функцией.
@bvaughn Я не нахожу ничего конкретного о том, что поддержка переполнения является ограничивающим фактором. Любопытно, я хотел бы знать, что это может быть. Я, конечно, понимаю, что поддержка основных функций для обоих может быть утомительной, но это выглядит только так, как будто элемент базового списка - это все, что на данный момент не может быть выбрано разработчиком. Что касается меня и всех, кто может использовать response-window со сценариями с фиксированным заголовком, было бы неплохо получить встроенную поддержку таблиц, встроенную в макеты таблиц. Использование display: table требует "некоторых" накладных расходов разработчика и является разовым макетом для окружающих приложений, которые случайно могут быть построены с использованием таблиц. Я всегда мог настроить переполнение или другие свойства через css (я все равно делаю это в текущей реализации). О возможности elementType не может быть и речи?
@bvaughn Я не нахожу ничего конкретного о том, что поддержка переполнения является ограничивающим фактором.
Возможно, я использовал не лучшую формулировку, но если вы посмотрите на песочницу, с которой я связан ( rrn61wkzwm ), вы увидите неожиданное поведение.
Вот еще один пример HTML: lx65871p69
HTMLSelectElement
( <tbody>
) игнорирует такие стили, как height
и overflow
что делает его бесполезным для работы с окнами. Вы можете «исправить» это, изменив режим отображения ( display: block
), но это лишает смысла использование HTMLTableElement
потому что это нарушает поведение изменения размера столбца.
Это поведение изменения размера столбца в любом случае нарушено для случая использования окон, потому что размер зависит от содержимого в столбцах (которое будет меняться при прокрутке пользователем).
но это только выглядит так, как будто элемент базового списка - это все, что на данный момент не может быть выбрано разработчиком ... Не может быть и речи о поддержке elementType?
Вы уже можете указать тип тега, если действительно хотите ( 2j0z718mwy ), хотя я не вижу, что это дает вам.
Что касается меня и всех, кто может использовать response-window со сценариями с фиксированным заголовком, было бы неплохо получить встроенную поддержку таблиц, встроенную в макеты таблиц.
Использование HTMLTableElement
было бы проблематичным по причинам, которые я объяснил выше. Если вам нужен макет таблицы / сетки с фиксированным заголовком, вы можете сделать это, используя один из обычных компонентов списка: pk78pvwnkx
Зачем тебе стол? Я думаю, вы можете добиться того же макета столбцов с помощью встроенных блоков или гибких макетов.
Может быть, для некоторой доступности требуется структура таблицы (например, для лучшего чтения экрана по сравнению с несемантическими div)? Я здесь предполагаю.
В этом случае я бы переопределил стиль отображения CSS и любые другие стили, присущие элементам таблицы.
Мой опыт создания сложного табличного компонента (с фиксированными / закрепленными заголовками сверху и слева, запутанной структурой colspan / rowspan и моделью данных для описания структуры, стоящей за ней) около девяти лет назад (тогда у нас не было React, никаких проблем с доступностью, и, насколько я помню, никакой виртуализации), мой коллега, который отвечал за этот компонент, пытался реализовать его в правильных элементах таблицы, боролся с тем, чтобы заставить макет вести себя определенным образом, а затем решил реализовать макет таблицы на чистом JavaScript из абсолютно позиционированные и размерные блоки div. Это решение сработало отлично: никаких странных переходов по макету, плавная прокрутка (не по строке / столбцу) и т. Д.
Может быть, для некоторой доступности требуется структура таблицы (например, для лучшего чтения экрана по сравнению с несемантическими div)? Я здесь предполагаю.
Для этого можно использовать роли Арии 😄
Очень тщательно, спасибо. Вы только что спасли меня, когда я спустился в кроличью нору, чтобы попытаться создать прототип, который решал бы одну проблему только для создания других.
Привет
Я попытался найти существующий поток вместо того, чтобы создавать новый. Надеюсь, я нахожусь в хорошем месте ...
Есть ли способ создать своего рода «colspan» для слияния двух ячеек для FixedSizeGrid
(вероятно, имеет больше смысла в моем контексте)?
Этот вопрос основан на другом обсуждении, начатом здесь , но для большей ясности я предпочитаю публиковать здесь.
Есть ли способ создать своего рода «colspan» для объединения двух ячеек для FixedSizeGrid (вероятно, имеет больше смысла в моем контексте)?
Нет. Это не поддерживается.
@einarq @BlaineBradbury @sompylasar Если вам все еще интересно, мне удалось получить оконную работу с тегами таблиц. Фактически, я закончил тем, что создал библиотеку, оборачивающую окно реакции. Вы можете увидеть живую демонстрацию здесь: https://window-table.netlify.com/
Причина, по которой мне нужны теги таблиц, была в основном для стилизации. Стилизовать обычную таблицу html с помощью tw-bootstrap довольно просто, и поэтому я хотел сделать то же самое с таблицей с окнами.
У меня возникает соблазн пометить и спросить Брайана, что он думает об этой реализации (поскольку он упомянул, что теги таблицы html не будут работать). Но он уже достаточно мне помог. Так что я оставлю это вам, ребята.
Спасибо.
Интересный подход @pupudu. Я не знаю, возникнут ли какие-либо проблемы с доступностью из-за наличия отдельных тегов <table>
для заголовков и строк, но в противном случае отличная идея.
Я пытаюсь использовать react-datasheet
с react-window
, в основном это работает:
function sheetRenderer(props) {
const Row = ({ index, style }) => (
React.cloneElement(props.children[index], { style })
);
return (
<table className={props.className}>
<tbody>
<FixedSizeList
height={150}
itemCount={1000}
itemSize={35}
width={300}
>
{Row}
</FixedSizeList>
</tbody>
</table>
)
}
export default function EntityTable(props: IEntityTableProps) {
const initialGrid = useMemo(() => {
return getTableGridFromCSV(props.entityListCSV);
}, [props.entityListCSV]);
const [modifiedGrid, updateModifiedGrid] = useImmer(initialGrid);
return (
<ReactDataSheet
data={modifiedGrid}
sheetRenderer={sheetRenderer}
valueRenderer={cell => cell.value}
onCellsChanged={changes => {
updateModifiedGrid(draft => {
changes.forEach(({ cell, row, col, value }) => {
draft[row][col].value = value || '';
});
});
}}
/>
);
}
function getTableGridFromCSV(csv: string) {
return csv.split('\n').map(row =>
row.split(',').map((cell, index) => {
if (index === 0) {
return {
value: cell,
forceComponent: true,
component: <button onClick={() => console.log(cell)}>{cell}</button>,
};
}
if (index === 2) {
return {
value: cell,
};
}
return {
value: cell,
component: <span>{cell}</span>,
};
}),
);
}
Он отображает, единственная проблема - Warning: validateDOMNesting(...): <tr> cannot appear as a child of <div>.
index.js:1437 Warning: validateDOMNesting(...): <div> cannot appear as a child of <tbody>.
Эй, я пробую это с помощью React-Table и замечаю, что мне нужно использовать div вместо элементов таблицы. Проблема в том, что библиотеки стилей, такие как material / bootstrap, полагаются на эти элементы. Так что изменить схему моей таблицы на div, а не на элементы - гораздо сложнее. Можно ли вообще использовать элементы таблицы для различий или мне нужно создать свой собственный стиль сейчас?
@simkessy Если вы еще не заметили, вам следует проверить window-table. Он позволяет использовать теги таблиц HTML, позволяя повторно использовать существующие стили. Однако следует признать, что таблица не такая продвинутая, как таблица реакции.
https://window-table.netlify.com/
@pupudu Я приветствую ваши усилия по открытому исходному
Оказывается, мне удалось добиться этого с помощью очень небольшого фрагмента кода и большого творчества. Код достаточно прост, чтобы любой мог копировать / вставлять и расширять его по своему усмотрению. @bvaughn, выяснив, как это сделать, было бы довольно тривиально добавить в библиотеку, если хотите, но также довольно легко переопределить, если вы знаете, как.
Вкратце :
Песочница рабочего кода: https://codesandbox.io/s/react-window-with-table-elements-d861o
Код для справки
import React from 'react'
import { useState, useRef, useContext } from 'react'
import { FixedSizeList, FixedSizeListProps } from 'react-window'
import { render } from 'react-dom'
/** Context for cross component communication */
const VirtualTableContext = React.createContext<{
top: number
setTop: (top: number) => void
header: React.ReactNode
footer: React.ReactNode
}>({
top: 0,
setTop: (value: number) => {},
header: <></>,
footer: <></>,
})
/** The virtual table. It basically accepts all of the same params as the original FixedSizeList.*/
function VirtualTable({
row,
header,
footer,
...rest
}: {
header?: React.ReactNode
footer?: React.ReactNode
row: FixedSizeListProps['children']
} & Omit<FixedSizeListProps, 'children' | 'innerElementType'>) {
const listRef = useRef<FixedSizeList | null>()
const [top, setTop] = useState(0)
return (
<VirtualTableContext.Provider value={{ top, setTop, header, footer }}>
<FixedSizeList
{...rest}
innerElementType={Inner}
onItemsRendered={props => {
const style =
listRef.current &&
// @ts-ignore private method access
listRef.current._getItemStyle(props.overscanStartIndex)
setTop((style && style.top) || 0)
// Call the original callback
rest.onItemsRendered && rest.onItemsRendered(props)
}}
ref={el => (listRef.current = el)}
>
{row}
</FixedSizeList>
</VirtualTableContext.Provider>
)
}
/** The Row component. This should be a table row, and noted that we don't use the style that regular `react-window` examples pass in.*/
function Row({ index }: { index: number }) {
return (
<tr>
{/** Make sure your table rows are the same height as what you passed into the list... */}
<td style={{ height: '36px' }}>Row {index}</td>
<td>Col 2</td>
<td>Col 3</td>
<td>Col 4</td>
</tr>
)
}
/**
* The Inner component of the virtual list. This is the "Magic".
* Capture what would have been the top elements position and apply it to the table.
* Other than that, render an optional header and footer.
**/
const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
function Inner({ children, ...rest }, ref) {
const { header, footer, top } = useContext(VirtualTableContext)
return (
<div {...rest} ref={ref}>
<table style={{ top, position: 'absolute', width: '100%' }}>
{header}
<tbody>{children}</tbody>
{footer}
</table>
</div>
)
}
)
/**
* Render Our Example
**/
render(
<VirtualTable
height={300}
width="100%"
itemCount={1000}
itemSize={36}
header={
<thead>
<tr>
<th>Index</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
</tr>
</thead>
}
row={Row}
footer={
<tfoot>
<tr>
<td>Footer 1</td>
<td>Footer 2</td>
<td>Footer 3</td>
<td>Footer 4</td>
</tr>
</tfoot>
}
/>,
document.querySelector('main')
)
@jamesmfriedman Люблю подход. Действительно интересная идея использования контекста для достижения этой цели. Мне нравится, что вы визуализируете только одну таблицу, в отличие от моего подхода, когда я визуализирую две, одну для заголовка и одну для тела. Это вызвало большую путаницу (не ожидал этого) у пользователей оконных таблиц.
Я постараюсь использовать эти идеи в оконном столе, если вы не против. Я думаю, что самой большой проблемой было бы выяснить, как автоматически изменять размер строк на основе содержимого (что было самой большой проблемой для windo-table, по крайней мере).
@jamesmfriedman, что выглядит очень многообещающим. @bvaughn есть ли у вас какие-либо опасения по поводу этого подхода?
@jamesmfriedman похоже, что заголовок прокручивается вместе с контентом. Можно ли сделать его липким?
На самом деле это возможно, а не только для данной реализации. Просто поищите в Google липкие заголовки с элементами таблицы HTML. Я смутно припоминаю, как это можно сделать - на самом деле сделать позицию элемента TH "липкой".
@jamesmfriedman большое спасибо за ваш пример 👍 это очень помогло @marink вот пример липких заголовков https://codesandbox.io/s/react-window-with-table-elements-jj70e вам нужно добавить style={{ position: 'sticky', top: 0 }}>
в теги th
@jamesmfriedman Большое спасибо за пример. Я собираюсь изучить его использование. Но я думаю, что можно было бы использовать top: 0 и position sticky вместо пересчета top и иметь абсолютную позицию в элементе table. Потому что, если вы используете position sticky для получения липких заголовков на th элементах, тогда все будет испорчено при быстрой прокрутке.
Итак, строка 79 будет <table style={{ top: 0, position: 'sticky', width: '100%' }}>
Это также устраняет проблему прокрутки, возникающую при продолжении прокрутки, когда вы находитесь внизу.
Еще одна веская причина для использования HTML-таблиц - поддержка IE11. Я использую FixedSizeList
а затем стилизую его с помощью CSS-сетки. Однако, когда вам нужно добавить другие функции, такие как адаптивные столбцы, столбцы разных размеров и т. Д., И заставить все это работать вместе с IE11, вы получите огромное количество кода. В то время как таблицы HTML по умолчанию работают без кода.
IE11 - это не то, что вам больше нужно поддерживать :)
Каждый разработчик FE желает смерти IE11. Но, к сожалению, есть компании / люди, которые не могут сдвинуться с мертвой точки по причинам, которые мы даже не можем себе представить. Надеюсь, это всего на несколько лет вперед. А пока нам нужно будет поддерживать IE11, нравится нам это или нет.
Мне тоже было трудно проглотить эту пилюлю.
@ olafur164 спасибо за ваше исправление, что липкие заголовки не ломаются при быстрой прокрутке. Знаете ли вы, есть ли способ сохранить "липкий" вид, поскольку теперь он прокручивает строку за раз, а не плавно?
Позвольте мне поделиться своим опытом с реакцией-виртуализацией (даже на странице проблем с реактивным окном ) и некоторой библиотекой пользовательского интерфейса материалов, называемой https://github.com/mbrn/ материал-таблица / issues / 891 # issuecomment -681986647. Есть еще некоторые проблемы, такие как проблемы со стилем и предупреждение validateDOMNesting(...)
.
@jamesmfriedman большое спасибо за ваш пример 👍 это очень помогло @marink вот пример липких заголовков. вам нужно добавить
style={{ position: 'sticky', top: 0 }}>
в тегиth
Привет, @JCofman , я попробовал исправить CSS, но у меня это не работает. Вот пример песочницы кода - https://codesandbox.io/s/react-window-with-table-elements-forked-huti6?file=/src/index.tsx : 514-542
Есть две проблемы -
Заранее спасибо :)
@jamesmfriedman Люблю подход. Действительно интересная идея использования контекста для достижения этой цели. Мне нравится, что вы визуализируете только одну таблицу, в отличие от моего подхода, когда я визуализирую две, одну для заголовка и одну для тела. Это вызвало большую путаницу (не ожидал этого) у пользователей оконных таблиц.
Я постараюсь использовать эти идеи в оконном столе, если вы не против. Я думаю, что самой большой проблемой было бы выяснить, как автоматически изменять размер строк на основе содержимого (что было самой большой проблемой для windo-table, по крайней мере).
В итоге я нашел очень похожее решение, потому что я использую display: grid
с display: contents
для строк, поэтому в основном придерживаюсь ограничения table > tr
elements.
Вы использовали context + refs для вызова внутреннего метода, однако в этом нет необходимости, поскольку то же самое можно сделать, просмотрев значение style.top первого дочернего элемента:
const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
function Inner({ children, ...rest }, ref) {
const { header, footer } = useContext(VirtualTableContext)
const {style} = children[0].props;
return (
<div {...rest} ref={ref}>
<table style={style}>
{header}
<tbody>{children}</tbody>
{footer}
</table>
</div>
)
}
)
Опора стиля задается библиотекой, когда она выполняет createElement для каждой строки, и поскольку ваш конкретный компонент Row
не назначает style
tr
, вы не передавая их тоже вниз.
Недавно я задумался о чем-то подобном. Что, если бы мы переместили все тело таблицы с заполнением, используя псевдоэлементы (после / до) через настраиваемые свойства css 🤔
В примере с использованием реакции-виртуального https://codesandbox.io/s/poc-react-virtual-table-jyz0m
Мне абсолютно нужна таблица, чтобы я мог достичь желаемого UX, и меня не устраивали обходные пути, чтобы заставить ее работать с react-window
.
В итоге я просто извлек логику вирутализации на крючок и реализовал ее с двумя таблицами, одна для заголовков, а вторая для содержимого, как и то, что было опубликовано выше. Разница в моем подходе заключается в том, что заголовки второй таблицы все еще присутствуют в разметке, но визуально скрыты, поэтому она остается доступной, тогда как заголовки первой таблицы предназначены только для зрячих пользователей и позиционно закреплены. Работало как шарм, и код был значительно проще.
Просто выбросить его там, на случай, если кто-то захочет это попробовать.
@piecyk Это отличный https://virtuoso.dev/grouped-by-first-letter/
Я должен добавить, что позиционирование всего контейнера с помощью absolute / top является эффективным, но при выполнении аудита производительности с Chrome я вижу проблемы CLS, которые могут повлиять на FPS. Я не думаю, что влияние заметно, вы можете увидеть, насколько быстрым и плавным оно может быть на этом примере: https://b6udg.csb.app/ (хотя это контейнер большого размера). Однако с padding-top / bottom CLS НЕТ!
Я попробую сделать это сам и скоро измерим разницу.
@pupudu Я приветствую ваши усилия по открытому исходному
Оказывается, мне удалось добиться этого с помощью очень небольшого фрагмента кода и большого творчества. Код достаточно прост, чтобы любой мог копировать / вставлять и расширять его по своему усмотрению. @bvaughn, выяснив, как это сделать, было бы довольно тривиально добавить в библиотеку, если хотите, но также довольно легко переопределить, если вы знаете, как.
_Кратко об этом_:
- Захватить "верхний" стиль первой строки после рендеринга.
- Сохраните это значение в React.Context, чтобы мы могли передавать его.
- Примените значение к компоненту таблицы, который будет перемещаться, а не к самим строкам
- Добавьте дополнительные слоты для таких вещей, как верхние и нижние колонтитулы.
- Эргономика библиотеки не позволяет аккуратно передавать вещи, поэтому React.Context - это герой, который преодолевает межкомпонентную коммуникацию.
Песочница рабочего кода: https://codesandbox.io/s/react-window-with-table-elements-d861o
Код для справки
import React from 'react' import { useState, useRef, useContext } from 'react' import { FixedSizeList, FixedSizeListProps } from 'react-window' import { render } from 'react-dom' /** Context for cross component communication */ const VirtualTableContext = React.createContext<{ top: number setTop: (top: number) => void header: React.ReactNode footer: React.ReactNode }>({ top: 0, setTop: (value: number) => {}, header: <></>, footer: <></>, }) /** The virtual table. It basically accepts all of the same params as the original FixedSizeList.*/ function VirtualTable({ row, header, footer, ...rest }: { header?: React.ReactNode footer?: React.ReactNode row: FixedSizeListProps['children'] } & Omit<FixedSizeListProps, 'children' | 'innerElementType'>) { const listRef = useRef<FixedSizeList | null>() const [top, setTop] = useState(0) return ( <VirtualTableContext.Provider value={{ top, setTop, header, footer }}> <FixedSizeList {...rest} innerElementType={Inner} onItemsRendered={props => { const style = listRef.current && // @ts-ignore private method access listRef.current._getItemStyle(props.overscanStartIndex) setTop((style && style.top) || 0) // Call the original callback rest.onItemsRendered && rest.onItemsRendered(props) }} ref={el => (listRef.current = el)} > {row} </FixedSizeList> </VirtualTableContext.Provider> ) } /** The Row component. This should be a table row, and noted that we don't use the style that regular `react-window` examples pass in.*/ function Row({ index }: { index: number }) { return ( <tr> {/** Make sure your table rows are the same height as what you passed into the list... */} <td style={{ height: '36px' }}>Row {index}</td> <td>Col 2</td> <td>Col 3</td> <td>Col 4</td> </tr> ) } /** * The Inner component of the virtual list. This is the "Magic". * Capture what would have been the top elements position and apply it to the table. * Other than that, render an optional header and footer. **/ const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>( function Inner({ children, ...rest }, ref) { const { header, footer, top } = useContext(VirtualTableContext) return ( <div {...rest} ref={ref}> <table style={{ top, position: 'absolute', width: '100%' }}> {header} <tbody>{children}</tbody> {footer} </table> </div> ) } ) /** * Render Our Example **/ render( <VirtualTable height={300} width="100%" itemCount={1000} itemSize={36} header={ <thead> <tr> <th>Index</th> <th>Header 2</th> <th>Header 3</th> <th>Header 4</th> </tr> </thead> } row={Row} footer={ <tfoot> <tr> <td>Footer 1</td> <td>Footer 2</td> <td>Footer 3</td> <td>Footer 4</td> </tr> </tfoot> } />, document.querySelector('main') )
Спасибо за это, пробовал ли кто-нибудь (с успехом) использовать это с компонентом InfiniteLoader
? ... Я пробовал пинать его, но у меня проблемы с внутренней "оболочкой", которую я Предположим, потому что бесконечный загрузчик передает неожиданные реквизиты в innerElementType.
Самый полезный комментарий
@pupudu Я приветствую ваши усилия по открытому исходному
Оказывается, мне удалось добиться этого с помощью очень небольшого фрагмента кода и большого творчества. Код достаточно прост, чтобы любой мог копировать / вставлять и расширять его по своему усмотрению. @bvaughn, выяснив, как это сделать, было бы довольно тривиально добавить в библиотеку, если хотите, но также довольно легко переопределить, если вы знаете, как.
Вкратце :
Песочница рабочего кода: https://codesandbox.io/s/react-window-with-table-elements-d861o
Код для справки