Мобильная обертка RDT с использованием React Context

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

Как вы уже прочитали в заголовке, для создания таблиц нам понадобится React Data Table Component (RDT), который представляет собой мощный пакет, предоставляющий хороший API для сортировки, пагинации, фильтрации, стилизации и многого другого.

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

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

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

Установка RDT

  • Установите RDT с помощью одной из следующих команд:
    • npm i react-data-table-component styled-components
    • yarn react-data-table-component styled-components
const columns = useMemo(() => [
  {
    name: 'Column name 1',
    id: 'columnId1',
    selector: ({ attribute1 }) => attribute1
  },
  {
    name: 'Column name 2',
    id: 'columnId2',
    selector: ({ attribute2 }) => attribute2
  },
  {
    name: 'actions',
    id: 'actions',
    cell: ({ attribute3 }) => (
      <div>
        <span onClick={(attribute3) => {}}Action 1</span>
      </div>
    ),
    hide: 'md'
  }
  // more columns...
], [])
Войти в полноэкранный режим Выйти из полноэкранного режима

Добавив свойство hide: 'md', если разрешение окна меньше разрешения рабочего стола, колонка будет автоматически скрыта, это просто, но теперь потребуется способ отображения на мобильных устройствах, и здесь пригодится ExpandedComponent.

Создание обертки

<ExpandedWrapper>
  <Item label="ColumnName">{plainValue}</Item>
  <Item label="ColumnName"><span>children</span></Item>
</ExpandedWrapper>
Вход в полноэкранный режим Выход из полноэкранного режима
  • Что такое ExpandedWrapper и Item? Оба компонента используются для поддержания согласованности стилей, и вы можете создавать свои собственные компоненты по своему усмотрению:

    • ExpandedWrapper

      const ExpandedWrapper = ({ children }) => {
        return (
          <div className="grid text-sm mr-4">
            {children}
          </div>
        )
      }
      
    • Item

      const Item = ({ label, children }) => {
        return (
          <div className="flex">
            <div className="max-w-max my-2 ml-16 font-semibold">
              <span>{label}</span>
            </div>
            <div className="max-w-max my-2 ml-4">
              <span>{children}</span>
            </div>
          </div>
        )
      }
      

В чем проблема?

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

import { createContext } from 'react'
const ExpandedComponentContext = createContext()

const ExpandedComponentProvider = ({ children, ...rest }) => {
  return (
    <ExpandedComponentContext.Provider value={{ ...rest }}>
      {children}
    </ExpandedComponentContext.Provider>
  )
}

export { ExpandedComponentProvider, ExpandedComponentContext }
Вход в полноэкранный режим Выход из полноэкранного режима
import { useContext } from 'react'
import { ExpandedComponentContext } from 'contexts/ExpandedComponentProvider'

const useExpandedComponent = () => {
  const context = useContext(ExpandedComponentContext)

  if (context === undefined) {
    throw new Error(
      'useExpandedComponent must be used within a ExpandedComponentProvider'
    )
  }

  return context
}

export default useExpandedComponent
Войти в полноэкранный режим Выход из полноэкранного режима

Теперь вы можете обернуть вашу таблицу с помощью ExpandedComponentProvider, чтобы разделить все функции или реквизиты, которые вы хотите, а затем в расширенном компоненте использовать хук useExpandedComponent, чтобы получить их все и использовать по своему усмотрению, примечание: expandableRows — это флаг, который нужно контролировать, когда вы хотите использовать расширенный компонент, например, используя медиа-запрос или функцию для получения ширины окна, например:

import { useCallback, useMemo } from 'react'
import { Table } from 'components/Table'
import { ExpandedComponentProvider } from 'contexts/ExpandedComponentProvider'
import ExpandedExampleComponent from 'components/ExpandedExampleComponent'

const Example = () => {
  const data = [
    {
      attribute1: 'attribute1'
    },
    {
      attribute2: 'attribute2'
    },
    {
      attribute3: 'attribute3'
    }
  ]

  const handleClick = useCallback(
    (url) => () => {
      window.open(url, '_blank', 'noopener,noreferrer,resizable')
    }, [])

  const columns = useMemo(() => [
    {
      name: 'Column name 1',
      id: 'columnId1',
      selector: ({ attribute1 }) => attribute1
    },
    {
      name: 'Column name 2',
      id: 'columnId2',
      selector: ({ attribute2 }) => attribute2
    },
    {
      name: 'Actions',
      id: 'actions',
      cell: ({ attribute3 }) => (
        <span onClick {handleClick(attribute3)}Action 1</span>
      ),
      hide: 'md'
    }
    // more columns...
  ], [])

  return (
    <ExpandedComponentProvider onClick={handleClick}>
      <Table
        name="demo"
        columns={columns}
        data={data || []}
        expandableRows
        expandableRowsComponent={ExpandedExampleComponent}
    // more props...
      />
    </ExpandedComponentProvider>
  )
}

export default Example
Войти в полноэкранный режим Выйти из полноэкранного режима

и ExpandedExampleComponent :

import { Item, ExpandedWrapper } from 'components/Table'
import useExpandedComponent from 'hooks/useExpandedComponent'

const ExpandedExampleComponent = ({ data }) => {
  const { onClick } = useExpandedComponent()
  const { attribute1, attribute2, attribute3 } = data

  return (
    <ExpandedWrapper>
      <Item label="Column Name 1">{attribute1}</Item>
      <Item label="Column Name 2">{attribute2}</Item>
      <Item label="Actions">
    <span onClick={onClick(attribute3)}Action 1</span>
      </Item>
    </ExpandedWrapper>
  )
}

export default ExpandedExampleComponent
Войти в полноэкранный режим Выйти из полноэкранного режима

Предварительный просмотр в реальном времени:

Репозиторий: https://github.com/AgusRdz/rdt-context-demo

Заключительные мысли

Как вы можете видеть, вы можете создавать удивительные таблицы с помощью RDT, а в сочетании с React Context вы также можете добавить простой способ работы с ними без особых усилий.

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

Счастливого кодинга!

Оцените статью
devanswers.ru
Добавить комментарий