Як створити адаптивну таблицю фіксованих даних за допомогою гачків React

В одному з моїх проектів використовується бібліотека Fixed-Data-Table-2 (FDT2), і вона чудово підходить для ефективного відтворення тонн рядків даних.

Їхня документація демонструє адаптивну таблицю, розмір якої змінюється залежно від ширини та висоти браузера.

Я думав, що було б круто поділитися цим прикладом за допомогою React Hooks.

Що таке React Hooks?

Це функції, які надають вам такі функції React, як гачки стану та життєвого циклу без класів ES6.

Деякі переваги є

  • ізолюючи логіку стану, полегшуючи тестування
  • обмін логікою стану без рендерингу реквізитів або компонентів вищого порядку
  • відокремлення проблем вашого додатку на основі логіки, а не гачків життєвого циклу
  • уникаючи класів ES6, оскільки вони химерні, а не насправді класи , і підводять навіть досвідчених розробників JavaScript

Детальніше див. В офіційному вступі Reacts в Hooks

ПОПЕРЕДЖЕННЯ: Не використовуйте у виробництві!

На момент написання цієї статті Хуки розташовані в альфа-версії. Їх API може змінюватися в будь-який час.

Я рекомендую вам експериментувати, отримувати задоволення та використовувати Хуки у своїх допоміжних проектах, але не у виробничому коді, поки вони не стануть стабільними.

Мета

Ми створимо адаптивну таблицю фіксованих даних. Він не буде занадто вузьким або занадто широким для нашої сторінки, він підійде в самий раз!

Налаштування

Ось посилання на GitHub та CodeSandbox.

git clone //github.com/yazeedb/Responsive-FDT2-Hooks/ cd Responsive-FDT2-Hooks npm install 

masterФілія має готовий проект, тому перевірка на startгілку , якщо ви хочете слідувати.

git checkout start

І запустити проект.

npm start

Додаток повинен працювати localhost:3000. Почнемо кодування.

Імпорт стилів таблиці

Спочатку ви захочете імпортувати таблицю стилів FDT2 index.js, щоб ваша таблиця не виглядала химерною.

Генерування підроблених даних

Нашій таблиці потрібні дані, так? Створіть файл у srcпапці з назвою getData.js.

Ми будемо використовувати чудову бібліотеку faker.js для генерації наших даних. Це вже прийшло з вашим npm install.

Ось джерело, якщо ви хочете скопіювати / вставити.

import faker from 'faker'; const createFakeRowData = () => ({ firstName: faker.name.firstName(), lastName: faker.name.lastName(), email: faker.internet.email(), city: faker.address.city(), salary: faker.random .number({ min: 50000, max: 500000 }) .toLocaleString('en-US', { style: 'currency', currency: 'USD' }) }); export default () => Array.from({ length: 2000 }, createFakeRowData); 

createFakeRowData повертає об’єкт із повним ім’ям, електронною поштою, містом та зарплатою в доларах США.

Наша експортована функція повертає 2000 з них.

Невідповідна таблиця

У нас є свої дані, давайте кодувати таблицю зараз.

Угорі index.jsімпортуйте наші дані та компоненти FDT2.

import { Table, Column, Cell } from 'fixed-data-table-2'; import getData from './getData'; 

І використовувати їх так.

function App() { const data = getData(); return (  { return {data[rowIndex][columnKey]}; }} /> { return {data[rowIndex][columnKey]}; }} /> { return {data[rowIndex][columnKey]}; }} /> { return {data[rowIndex][columnKey]}; }} /> { return {data[rowIndex][columnKey]}; }} />
); }

Ми налаштовуємо таблицю з нашими даними і створюємо Columnдля кожного поля, яке ми хочемо відображати.

getData об’єкти містять ім’я / прізвище, електронну адресу, місто та заробітну плату, тому нам потрібен стовпець для кожного.

Наш інтерфейс зараз виглядає так.

Спробуйте змінити розмір вікна браузера, ви помітите, що воно взагалі не реагує. Він занадто великий або занадто малий для вашого вікна перегляду і може залишити зайвий простір.

Втеча до нечистого

Як ми дізналися, декларативний характер React дозволяє писати свій інтерфейс, використовуючи чисті, детерміновані та легко перевіряються функції.

Один і той же вхід повинен завжди повертати однаковий результат.

Однак нам іноді потрібно відвідати «нечистий» світ для маніпулювання DOM, додаючи події, такі як слухачі, підписки та таймери.

HOCS та візуалізація реквізиту

Візуалізація реквізитів та компонентів вищого порядку (HOCS) є стандартним рішенням, але є деякі компроміси, які зараз намагається вирішити Хук.

Використання гачків

Гачки - це новий евакуаційний люк для використання імперативного коду. У нашому випадку отримання розміру вікна - це той ефект, який ми шукаємо.

Створіть новий файл із назвою useWindowSize.js.

Для досягнення цього нам знадобляться дві речі:

  1. Listen to the window’s resize event, so we’re notified of when it changes
  2. Save the width/height to share with our table

Two hooks can help:

  1. useEffect
  2. useState

useEffect

This will likely replace your componentDidMount, componentDidUpdate, and componentWillUnmount lifecycle hooks once it’s stabilized.

useEffect's perfect for most initialization logic and reading the DOM.

It’s where we’ll set up our window resize event listeners.

For more detail, see the official docs.

useState

Super simple, this Hook returns a stateful value and a function to update it. Once we capture the window’s width/height, we’ll have useState track it.

Writing our custom Hook

According to the official docs:

A custom Hook is a JavaScript function whose name starts with ”use” and that may call other Hooks.

Our custom hook will be called useWindowSize, and it’ll call the useState and useEffect hooks.

This Hook’s mainly from Gabe Ragland’s useWindowSize on useHooks.com.

// `useWindowSize.js` import { useState, useEffect } from 'react'; export default () => { const getSize = () => { return { width: window.innerWidth, height: window.innerHeight }; }; const [windowSize, setWindowSize] = useState(getSize); useEffect(() => { const handleResize = () => { setWindowSize(getSize()); }; window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []); return windowSize; }; 

Let’s break this down.

Getting the window size

const getSize = () => { return { width: window.innerWidth, height: window.innerHeight }; }; 

getSize simply returns the window’s innerWidth and innerHeight.

Initializing useState

const [windowSize, setWindowSize] = useState(getSize); 

useState can take an initial value or a function that returns a value.

In this case we want the window’s dimensions to start, so getSize is the perfect initializer.

useState then returns an array, the first index is the value and the second index is the updater function.

Configuring useEffect

useEffect(() => { const handleResize = () => { setWindowSize(getSize()); }; window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []); 

useEffect takes a function that will run your desired effect.

Whenever the window size changes, handleResize sets the state by giving setWindowSize the latest width/height.

Cleanup Logic

Our effect function then returns a new function, which useEffect recognizes as cleanup logic.

return () => { window.removeEventListener('resize', handleResize); }; 

When we leave the page or somehow unmount our component, this cleanup function runs and removes the resize event listener. This helps prevent memory leaks.

useEffect’s Second Argument

useEffect's first argument is the function handling our logic, but we also gave it a second argument: an empty array.

useEffect(() => { ... }, []); // empty array 

Why an empty array?

useEffect's second argument is an array of values to watch over. If any of those values change useEffect runs again.

We’re just setting/removing event listeners, which only needs to happen once.

An empty array is how we communicate “just run once” to useEffect.

Empty array = no values ever change = just run once

Return windowSize

Now that our effect’s set up, just return windowSize. As the browser’s resized, windowSize will be updated.

Using our custom Hook

Time to throw our Hook at Fixed-Data-Table2!

Back in index.js, go ahead and import useWindowSize.

And use it like so.

For fun you can console.log(windowSize) and watch it update in real-time.

Cool, we get back an object of the window’s width and height!

Instead of hardcoding our table’s width and height, we can use our Hook’s exposed state.

Now your table should adjust to the window’s dimensions.

I hope you enjoyed this tutorial!