Cara membuat Jadual Data-Tetap yang responsif dengan Kait Reaksi

Salah satu projek saya menggunakan perpustakaan yang disebut Fixed-Data-Table-2 (FDT2), dan bagus untuk menghasilkan banyak baris data dengan cekap.

Dokumentasi mereka menunjukkan jadual responsif yang mengubah ukurannya berdasarkan lebar dan tinggi penyemak imbas.

Saya fikir akan senang untuk berkongsi contoh ini menggunakan React Hooks.

Apakah Cangkuk React?

Fungsi-fungsi tersebut memberi anda ciri-ciri React seperti cangkuk keadaan dan kitaran hidup tanpa kelas ES6.

Beberapa faedahnya adalah

  • mengasingkan logik keadaan, menjadikannya lebih mudah untuk diuji
  • berkongsi logik bernegara tanpa alat peraga atau komponen yang lebih tinggi
  • memisahkan kebimbangan aplikasi anda berdasarkan logik, bukan cangkuk kitaran hidup
  • mengelakkan kelas ES6, kerana mereka unik, bukan kelas sebenarnya , dan malah membuat pembangun JavaScript yang berpengalaman

Untuk lebih terperinci, lihat pengenalan rasmi Hooks React.

PERINGATAN: Jangan gunakan dalam pengeluaran!

Pada masa penulisan ini, Hooks berada dalam alpha. API mereka boleh berubah pada bila-bila masa.

Saya cadangkan anda bereksperimen, bersenang-senang, dan menggunakan Cangkuk dalam projek sampingan anda, tetapi tidak dalam kod pengeluaran sehingga ia stabil.

Matlamat

Kami akan membina Jadual Data-Tetap yang responsif. Ia tidak akan terlalu sempit atau terlalu lebar untuk halaman kami, ia akan sesuai dengan betul!

Persediaan

Berikut adalah pautan GitHub dan CodeSandbox.

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

The masterranting mempunyai projek selesai, jadi checkout startcawangan jika anda ingin mengikuti bersama-sama.

git checkout start

Dan jalankan projek.

npm start

Aplikasi harus berjalan localhost:3000. Mari mulakan pengekodan.

Mengimport gaya jadual

Mula-mula anda ingin mengimport lembaran gaya FDT2 index.js, supaya jadual anda tidak kelihatan serba salah.

Menjana data palsu

Jadual kami memerlukan data, bukan? Buat fail dalam srcfolder yang dipanggil getData.js.

Kami akan menggunakan perpustakaan faker.js yang hebat untuk menghasilkan data kami. Itu sudah disertakan dengan anda npm install.

Inilah sumbernya jika anda mahu menyalin / menampal.

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 mengembalikan objek dengan nama penuh, e-mel, bandar, dan gaji dalam dolar AS.

Fungsi yang dieksport kami mengembalikan 2000 daripadanya.

Jadual yang tidak responsif

Kami mempunyai data kami, mari kod jadual sekarang.

Di bahagian atas index.js, import data dan komponen FDT2 kami.

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

Dan gunakan seperti itu.

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]}; }} />
        
       
      
     
    
    
); }

Kami mengkonfigurasi jadual dengan data kami dan membuat Columnuntuk setiap bidang yang ingin kami paparkan.

getData objek mengandungi nama depan / belakang, e-mel, bandar, dan gaji, jadi kami memerlukan lajur untuk masing-masing.

UI kami kini kelihatan seperti ini.

Try resizing your browser window, you’ll notice it isn’t responsive at all. It’s either too big or too small for your viewport and can leave excess space.

Escape to the impure

As we’ve learned, React’s declarative nature lets you write your UI using pure, deterministic, and easily testable functions.

The same input should always return the same output.

However, we sometimes need to visit the “impure” world, for DOM manipulation, adding events such as listeners, subscriptions, and timers.

HOCS and render props

Render props and higher-order components (HOCS) are the standard solution, but have some tradeoffs that Hooks are now trying to solve.

Using Hooks

Hooks are the new escape hatch to use imperative code. In our case, getting the window size is the effect we’re after.

Create a new file called useWindowSize.js.

We’ll need two things to achieve this:

  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!