Tutorial

Cara Membangun Paginasi Khusus dengan React

Published on December 16, 2020
authorauthor

Glad Chinda and Bradley Kouchi

Bahasa Indonesia
Cara Membangun Paginasi Khusus dengan React

Pengantar

Kita sering terlibat dalam pembuatan aplikasi web yang mengharuskan kita mengambil set catatan data yang besar dari server jauh, API, atau basis data. Jika Anda membangun sistem pembayaran, misalnya, sistem ini dapat mengambil ribuan transaksi. Jika contohnya adalah aplikasi media sosial, aplikasi ini dapat mengambil banyak komentar, profil, atau kegiatan pengguna. Apa pun kasusnya, ada beberapa solusi untuk menyajikan data dengan cara yang tidak menyulitkan pengguna akhir yang berinteraksi dengan aplikasi tersebut.

Salah satu metode untuk menangani set data besar adalah menggunakan paginasi. Paginasi bekerja secara efektif saat Anda sudah mengetahui ukuran set data (total jumlah catatan dalam set data). Kedua, Anda hanya memuat potongan data yang diperlukan dari set data total berdasarkan interaksi pengguna akhir dengan kontrol paginasi. Ini adalah teknik yang digunakan untuk menampilkan hasil pencarian di Google Search.

Dalam tutorial ini, kita akan mempelajari cara membangun komponen paginasi khusus dengan React untuk melakukan paginasi pada set data yang besar. Anda akan membangun tampilan terpaginasi dari negara-negara di dunia - suatu set data dengan ukuran yang sudah diketahui.

Berikut ini adalah peragaan yang akan Anda bangun dalam tutorial ini:

Tangkapan Layar Aplikasi Demo — menampilkan negara-negara di dunia

Prasyarat

Untuk menyelesaikan tutorial ini, Anda akan memerlukan:

Tutorial ini diverifikasi dengan Node v14.2.0, npm v6.14.4, react v16.13.1, dan react-scripts v3.4.1.

Langkah 1 — Menyiapkan Proyek

Mulai aplikasi React yang baru menggunakan perintah create-react-app. Anda dapat menamakan aplikasi sesuai keinginan Anda, tetapi tutorial ini akan menamakannya react-pagination:

  1. npx create-react-app react-pagination

Selanjutnya, Anda akan menginstal dependensi yang diperlukan untuk aplikasi Anda. Pertama-tama, gunakan jendela terminal untuk bernavigasi ke direktori proyek:

  1. cd react-pagination

Jalankan perintah berikut untuk menginstal dependensi yang diperlukan:

  1. npm install bootstrap@4.1.0 prop-types@15.6.1 react-flags@0.1.13 countries-api@2.0.1 node-sass@4.14.1

Ini akan menginstal bootstrap, prop-types, react-flags, countries-api, dan node-sass.

Anda menginstal paket bootstrap sebagai dependensi untuk aplikasi karena Anda akan membutuhkan beberapa penataan gaya asali. Anda juga akan menggunakan gaya dari komponen pagination Bootstrap.

Untuk menyertakan Bootstrap dalam aplikasi, edit berkas src/index.js:

  1. nano src/index.js

Dan tambahkan baris berikut sebelum pernyataan import lainnya:

src/index.js
import "bootstrap/dist/css/bootstrap.min.css";

Sekarang, penataan gaya Bootstrap akan tersedia di seluruh aplikasi Anda.

Anda juga telah menginstal react-flags sebagai dependensi untuk aplikasi Anda. Untuk mendapatkan akses ke ikon bendera dari aplikasi, Anda perlu menyalin citra ikon ke direktori public aplikasi Anda.

Buat direktori img dalam direktori public Anda:

  1. mkdir public/img

Salin berkas citra dalam flags ke img:

  1. cp -R node_modules/react-flags/vendor/flags public/img

Ini menyediakan salinan dari semua citra react-flag untuk aplikasi Anda.

Karena Anda sudah menyertakan sebagian dependensi, mulailah aplikasi dengan menjalankan perintah berikut menggunakan npm dari direktori proyek react-pagination:

  1. npm start

Karena Anda telah memulai aplikasi, pengembangan dapat dimulai. Perhatikan bahwa tab peramban telah dibuka untuk Anda dengan fungsionalitas pemuatan ulang langsung agar tetap sinkron dengan aplikasi seiring Anda mengembangkannya.

Di titik ini, tampilan aplikasi akan terlihat seperti tangkapan layar berikut:

Tampilan Awal – Layar Welcome to React

Anda kini siap untuk mulai menciptakan komponen.

Langkah 2 — Menciptakan Komponen CountryCard

Dalam langkah ini, Anda akan menciptakan komponen CountryCard. Komponen CountryCard merender nama, wilayah, dan bendera dari negara yang diberikan.

Pertama-tama, mari kita ciptakan direktori component dalam direktori src:

  1. mkdir src/components

Kemudian, ciptakan berkas CountryCard.js yang baru dalam direktori src/components:

  1. nano src/components/CountryCard.js

Lalu, tambahkan snippet kode berikut padanya:

src/components/CountryCard.js
import React from 'react';
import PropTypes from 'prop-types';
import Flag from 'react-flags';

const CountryCard = props => {
  const {
    cca2: code2 = '', region = null, name = {}
  } = props.country || {};

  return (
    <div className="col-sm-6 col-md-4 country-card">
      <div className="country-card-container border-gray rounded border mx-2 my-3 d-flex flex-row align-items-center p-0 bg-light">
        <div className="h-100 position-relative border-gray border-right px-2 bg-white rounded-left">
          <Flag country={code2} format="png" pngSize={64} basePath="./img/flags" className="d-block h-100" />
        </div>
        <div className="px-3">
          <span className="country-name text-dark d-block font-weight-bold">{ name.common }</span>
          <span className="country-region text-secondary text-uppercase">{ region }</span>
        </div>
      </div>
    </div>
  )
}

CountryCard.propTypes = {
  country: PropTypes.shape({
    cca2: PropTypes.string.isRequired,
    region: PropTypes.string.isRequired,
    name: PropTypes.shape({
      common: PropTypes.string.isRequired
    }).isRequired
  }).isRequired
};

export default CountryCard;

Komponen CountryCard membutuhkan properti country yang berisi data tentang negara yang harus dirender. Seperti terlihat dalam propTypes untuk komponen CountryCard, objek properti country harus berisi data berikut:

  • cca2 - kode negara 2 digit
  • region - wilayah negara (misalnya: “Afrika”)
  • name.common - nama umum dari negara tersebut (misalnya: “Nigeria”)

Berikut ini adalah objek negara sampel:

{
  cca2: "NG",
  region: "Africa",
  name: {
    common: "Nigeria"
  }
}

Juga, perhatikan cara Anda merender bendera negara menggunakan paket react-flags. Anda dapat membaca [dokumentasi react-flags] react-flagsuntuk mempelajari lebih lanjut tentang properti yang diperlukan dan cara menggunakan paket tersebut.

Kini Anda telah menyelesaikan satu komponen CountryCard. Pada akhirnya, Anda akan menggunakan CountryCard berkali-kali untuk menampilkan bendera dan informasi negara yang berbeda dalam aplikasi Anda.

Langkah 3 — Menciptakan Komponen Pagination

Dalam langkah ini, Anda akan menciptakan komponen Pagination. Komponen Pagination berisi logika untuk membangun, merender, dan beralih halaman pada kontrol paginasi.

Ciptakan berkas Pagination.js yang baru dalam direktori src/components:

  1. nano src/components/Pagination.js

Lalu, tambahkan cuplikan kode berikut padanya:

src/components/Pagination.js
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';

class Pagination extends Component {
  constructor(props) {
    super(props);
    const { totalRecords = null, pageLimit = 30, pageNeighbours = 0 } = props;

    this.pageLimit = typeof pageLimit === 'number' ? pageLimit : 30;
    this.totalRecords = typeof totalRecords === 'number' ? totalRecords : 0;

    // pageNeighbours can be: 0, 1 or 2
    this.pageNeighbours = typeof pageNeighbours === 'number'
      ? Math.max(0, Math.min(pageNeighbours, 2))
      : 0;

    this.totalPages = Math.ceil(this.totalRecords / this.pageLimit);

    this.state = { currentPage: 1 };
  }
}

Pagination.propTypes = {
  totalRecords: PropTypes.number.isRequired,
  pageLimit: PropTypes.number,
  pageNeighbours: PropTypes.number,
  onPageChanged: PropTypes.func
};

export default Pagination;

Komponen Pagination dapat menggunakan empat properti khusus seperti yang ditentukan dalam objek propTypes.

  • onPageChanged adalah fungsi yang dipanggil dengan data dari keadaan paginasi saat ini hanya ketika halaman saat ini berubah.
  • totalRecords menunjukkan jumlah total catatan yang harus dipaginasikan. Ini wajib diisi.
  • pageLimit menunjukkan jumlah catatan yang ditampilkan per halaman. Jika tidak ditentukan, nilai asalinya adalah 30 seperti didefinisikan dalam constructor().
  • pageNeighbours menunjukkan jumlah nomor halaman tambahan yang ditampilkan di setiap sisi dari halaman saat ini. Nilai minimumnya adalah 0, dan nilai maksimumnya adalah 2. Jika tidak ditentukan, nilai asalinya adalah 0 seperti didefinisikan dalam constructor().

Gambar berikut ini mengilustrasikan efek dari nilai-nilai yang berbeda dari properti pageNeighbours:

Ilustrasi Page Neighbours

Dalam fungsi constructor(), Anda melakukan komputasi halaman total seperti berikut:

this.totalPages = Math.ceil(this.totalRecords / this.pageLimit);

Perhatikan bahwa Anda menggunakan Math.ceil() di sini yang memastikan bahwa Anda mendapatkan nilai integer untuk jumlah total halaman. Ini juga memastikan bahwa kelebihan catatan ditangkap dalam halaman terakhir, khususnya dalam kasus saat jumlah kelebihan catatan kurang dari jumlah catatan yang harus ditampilkan per halaman.

Terakhir, Anda menginisialisasi keadaan dengan properti currentPage menjadi 1. Anda memerlukan properti keadaan ini untuk melacak halaman yang aktif saat ini secara internal.

Selanjutnya, Anda akan menciptakan metode untuk menghasilkan nomor halaman.

Setelah import tetapi sebelum kelas Pagination, tambahkan konstanta berikut dan fungsi range:

src/components/Pagination.js
// ...

const LEFT_PAGE = 'LEFT';
const RIGHT_PAGE = 'RIGHT';

/**
 * Helper method for creating a range of numbers
 * range(1, 5) => [1, 2, 3, 4, 5]
 */
const range = (from, to, step = 1) => {
  let i = from;
  const range = [];

  while (i <= to) {
    range.push(i);
    i += step;
  }

  return range;
}

Dalam kelas Pagination, setelah constructor, tambahkan metode fetchPageNumbers berikut:

src/components/Pagination.js
class Pagination extends Component {
  // ...

  /**
   * Let's say we have 10 pages and we set pageNeighbours to 2
   * Given that the current page is 6
   * The pagination control will look like the following:
   *
   * (1) < {4 5} [6] {7 8} > (10)
   *
   * (x) => terminal pages: first and last page(always visible)
   * [x] => represents current page
   * {...x} => represents page neighbours
   */
  fetchPageNumbers = () => {
    const totalPages = this.totalPages;
    const currentPage = this.state.currentPage;
    const pageNeighbours = this.pageNeighbours;

    /**
     * totalNumbers: the total page numbers to show on the control
     * totalBlocks: totalNumbers + 2 to cover for the left(<) and right(>) controls
     */
    const totalNumbers = (this.pageNeighbours * 2) + 3;
    const totalBlocks = totalNumbers + 2;

    if (totalPages > totalBlocks) {
      const startPage = Math.max(2, currentPage - pageNeighbours);
      const endPage = Math.min(totalPages - 1, currentPage + pageNeighbours);
      let pages = range(startPage, endPage);

      /**
       * hasLeftSpill: has hidden pages to the left
       * hasRightSpill: has hidden pages to the right
       * spillOffset: number of hidden pages either to the left or to the right
       */
      const hasLeftSpill = startPage > 2;
      const hasRightSpill = (totalPages - endPage) > 1;
      const spillOffset = totalNumbers - (pages.length + 1);

      switch (true) {
        // handle: (1) < {5 6} [7] {8 9} (10)
        case (hasLeftSpill && !hasRightSpill): {
          const extraPages = range(startPage - spillOffset, startPage - 1);
          pages = [LEFT_PAGE, ...extraPages, ...pages];
          break;
        }

        // handle: (1) {2 3} [4] {5 6} > (10)
        case (!hasLeftSpill && hasRightSpill): {
          const extraPages = range(endPage + 1, endPage + spillOffset);
          pages = [...pages, ...extraPages, RIGHT_PAGE];
          break;
        }

        // handle: (1) < {4 5} [6] {7 8} > (10)
        case (hasLeftSpill && hasRightSpill):
        default: {
          pages = [LEFT_PAGE, ...pages, RIGHT_PAGE];
          break;
        }
      }

      return [1, ...pages, totalPages];
    }

    return range(1, totalPages);
  }
}

Di sini, pertama-tama Anda mendefinisikan dua konstanta: LEFT_PAGE dan RIGHT_PAGE. Konstanta ini akan digunakan untuk menunjukkan titik-titik dengan kontrol halaman untuk membalik ke kiri dan kanan, secara berurutan.

Anda juga mendefinisikan fungsi range() pembantu yang dapat membantu Anda menghasilkan rentang halaman.

Catatan: Jika Anda menggunakan pustaka utilitas seperti Lodash lodashdalam proyek, Anda dapat menggunakan fungsi _.range() yang disediakan oleh Lodash sebagai gantinya. Cuplikan kode berikut menunjukkan perbedaan antara fungsi range() yang baru saja Anda definisikan dan fungsi dari Lodash:

range(1, 5); // returns [1, 2, 3, 4, 5]
_.range(1, 5); // returns [1, 2, 3, 4]

Selanjutnya, Anda mendefinisikan metode fetchPageNumbers() dalam kelas Pagination. Metode ini menangani logika inti untuk menghasilkan nomor halaman yang ditampilkan pada kontrol paginasi. Anda ingin halaman pertama dan halaman terakhir agar selalu terlihat.

Pertama-tama, definisikan beberapa variabel. totalNumbers mewakili jumlah nomor halaman total yang akan ditampilkan pada kontrol. totalBlocks mewakili jumlah nomor halaman total yang ditampilkan ditambah dua blok tambahan untuk indikator halaman kiri dan kanan.

Jika totalPages tidak lebih besar dari totalBlocks, Anda menghasilkan rentang nomor dari 1 hingga totalPages. Sebaliknya, Anda menghasilkan larik dari nomor halaman, dengan LEFT_PAGE dan RIGHT_PAGE di titik-titik tempat Anda memiliki halaman yang tercecer ke kiri dan kanan, secara berurutan.

Meskipun begitu, perhatikan bahwa kontrol paginasi Anda memastikan bahwa halaman pertama dan halaman terakhir selalu terlihat. Kontrol halaman kiri dan kanan muncul ke arah dalam.

Sekarang, Anda akan menambahkan metode render() untuk memungkinkan Anda merender kontrol paginasi.

Dalam kelas Pagination, setelah constructor dan metodefetchPageNumbers, tambahkan metode render berikut:

src/components/Pagination.js
class Pagination extends Component {
  // ...

  render() {
    if (!this.totalRecords || this.totalPages === 1) return null;

    const { currentPage } = this.state;
    const pages = this.fetchPageNumbers();

    return (
      <Fragment>
        <nav aria-label="Countries Pagination">
          <ul className="pagination">
            { pages.map((page, index) => {

              if (page === LEFT_PAGE) return (
                <li key={index} className="page-item">
                  <a className="page-link" href="#" aria-label="Previous" onClick={this.handleMoveLeft}>
                    <span aria-hidden="true">&laquo;</span>
                    <span className="sr-only">Previous</span>
                  </a>
                </li>
              );

              if (page === RIGHT_PAGE) return (
                <li key={index} className="page-item">
                  <a className="page-link" href="#" aria-label="Next" onClick={this.handleMoveRight}>
                    <span aria-hidden="true">&raquo;</span>
                    <span className="sr-only">Next</span>
                  </a>
                </li>
              );

              return (
                <li key={index} className={`page-item${ currentPage === page ? ' active' : ''}`}>
                  <a className="page-link" href="#" onClick={ this.handleClick(page) }>{ page }</a>
                </li>
              );

            }) }

          </ul>
        </nav>
      </Fragment>
    );
  }
}

Di sini, Anda menghasilkan array nomor halaman dengan memanggil metode fetchPageNumbers() yang Anda ciptakan sebelumnya. Kemudian, Anda merender setiap nomor halaman menggunakan Array.prototype.map(). Perhatikan bahwa Anda mendaftarkan penangan peristiwa klik di setiap nomor halaman yang dirender untuk menangani klik.

Juga, perhatikan bahwa kontrol paginasi tidak akan dirender jika prop totalRecords tidak diberikan dengan benar ke komponen Pagination atau jika hanya ada 1 halaman.

Terakhir, Anda akan mendefinisikan metode penangan peristiwa.

Dalam kelas Pagination, setelah constructor dan metode fetchPageNumbers serta metode render, tambahkan yang berikut:

src/components/Pagination.js
class Pagination extends Component {
  // ...

  componentDidMount() {
    this.gotoPage(1);
  }

  gotoPage = page => {
    const { onPageChanged = f => f } = this.props;
    const currentPage = Math.max(0, Math.min(page, this.totalPages));
    const paginationData = {
      currentPage,
      totalPages: this.totalPages,
      pageLimit: this.pageLimit,
      totalRecords: this.totalRecords
    };

    this.setState({ currentPage }, () => onPageChanged(paginationData));
  }

  handleClick = page => evt => {
    evt.preventDefault();
    this.gotoPage(page);
  }

  handleMoveLeft = evt => {
    evt.preventDefault();
    this.gotoPage(this.state.currentPage - (this.pageNeighbours * 2) - 1);
  }

  handleMoveRight = evt => {
    evt.preventDefault();
    this.gotoPage(this.state.currentPage + (this.pageNeighbours * 2) + 1);
  }
}

Anda mendefinisikan metode gotoPage() yang memodifikasi keadaan dan mengatur currentPage menjadi halaman yang ditentukan. Ini memastikan bahwa argumen page memiliki nilai minimum 1 dan nilai maksimum sebesar jumlah total halaman. Pada akhirnya, ini memanggil fungsi onPageChanged() yang diberikan sebagai prop, dengan data menunjukkan keadaan paginasi yang baru.

Saat komponen terpasang, Anda pergi ke halaman pertama dengan memanggil this.gotoPage(1) seperti yang ditampilkan dalam metode siklus hidup componentDidMount().

Perhatikan cara Anda menggunakan (this.pageNeighbours * 2) dalam handleMoveLeft() dan handleMoveRight() untuk menggeser nomor halaman ke kiri dan ke kanan secara berurutan berdasarkan nomor halaman saat ini.

Berikut adalah demo dari interaksi pergerakan dari kiri ke kanan.

Pergerakan Kiri-Kanan dari interaksi

Kini Anda telah menyelesaikan komponen Pagination. Pengguna akan dapat berinteraksi dengan kontrol navigasi dalam komponen ini untuk menampilkan halaman berbeda dari bendera.

Langkah 4 — Membangun Komponen App

Karena Anda memiliki komponen CountryCard dan Pagination, Anda dapat menggunakannya dalam komponen App.

Modifikasi berkas App.js dalam direktori src:

  1. nano src/App.js

Gantikan konten dari App.js dengan baris kode berikut:

src/App.js
import React, { Component } from 'react';
import Countries from 'countries-api';
import './App.css';
import Pagination from './components/Pagination';
import CountryCard from './components/CountryCard';

class App extends Component {
  state = { allCountries: [], currentCountries: [], currentPage: null, totalPages: null }

  componentDidMount() {
    const { data: allCountries = [] } = Countries.findAll();
    this.setState({ allCountries });
  }

  onPageChanged = data => {
    const { allCountries } = this.state;
    const { currentPage, totalPages, pageLimit } = data;
    const offset = (currentPage - 1) * pageLimit;
    const currentCountries = allCountries.slice(offset, offset + pageLimit);

    this.setState({ currentPage, currentCountries, totalPages });
  }
}

export default App;

Di sini, Anda menginisialisasi keadaan komponen App dengan atribut berikut:

  • allCountries - Ini adalah larik dari semua negara dalam aplikasi Anda. Diinisialisasi menjadi larik yang kosong ([]).
  • currentCountries - Ini adalah larik dari semua negara yang ditampilkan pada halaman aktif saat ini. Diinisialisasi menjadi larik yang kosong ([]).
  • currentPage - Nomor halaman dari halaman yang aktif saat ini. Diinisialisasi menjadi null.
  • totalPages - Jumlah total halaman untuk semua catatan negara. Diinisialisasi menjadi null.

Selanjutnya, dalam metode siklus hidup componentDidMount(), Anda mengambil semua negara-negara di dunia menggunakan paket countries-api dengan memanggil Countries.findAll(). Kemudian, Anda memperbarui keadaan aplikasi, mengatur allCountries untuk memuat semua negara dunia. Anda dapat melihat [dokumentasi countries-api] countries-apiuntuk mempelajari lebih lanjut tentang paket tersebut.

Terakhir, Anda mendefinisikan metode onPageChanged(), yang akan dipanggil setiap kali Anda bernavigasi ke halaman baru dari kontrol paginasi. Metode ini akan diberikan ke properti onPageChanged dari komponen Pagination.

Ada dua baris yang layak diperhatikan dalam metode ini. Yang pertama adalah baris ini:

const offset = (currentPage - 1) * pageLimit;

Nilai offset menunjukkan indeks permulaan untuk mengambil catatan halaman saat ini. Menggunakan (currentPage - 1) memastikan bahwa offset berbasis nol. Mari kita anggap sebagai contoh, bahwa Anda menampilkan 25 catatan per halaman, dan Anda saat ini sedang melihat halaman 5. Kemudian, offset adalah ((5 - 1) * 25 = 100).

Misalnya, jika Anda mengambil catatan sesuai permintaan dari basis data, ini adalah kueri SQL sampel untuk menunjukkan kepada Anda bagaimana offset dapat digunakan:

SELECT * FROM `countries` LIMIT 100, 25

Karena Anda tidak mengambil catatan dari basis data atau sumber eksternal, Anda memerlukan cara untuk mengekstrak potongan catatan yang diperlukan guna ditampilkan di halaman saat ini.

Yang kedua adalah baris ini:

const currentCountries = allCountries.slice(offset, offset + pageLimit);

Di sini, Anda menggunakan metode Array.prototype.slice() untuk mengekstrak potongan catatan yang diperlukan dari allCountries dengan memberikan offset sebagai indeks permulaan untuk irisan dan (offset + pageLimit) sebagai indeks untuk mengakhiri irisan.

Catatan: Dalam tutorial ini, Anda tidak mengambil catatan dari sumber eksternal apa pun. Dalam aplikasi nyata, Anda mungkin akan mengambil catatan dari basis data atau API. Logika untuk mengambil catatan dapat diterapkam dalam metode onPageChanged() dari komponen App.

Mari kita anggap Anda memiliki titik akhir API fiktif /api/countries?page={current_page}&limit={page_limit}. Snippet berikut menunjukkan cara Anda dapat mengambil negara-negara sesuai permintaan dari API dengan menggunakan paket HTTP axios:

onPageChanged = data => {
  const { currentPage, totalPages, pageLimit } = data;

  axios.get(`/api/countries?page=${currentPage}&limit=${pageLimit}`)
    .then(response => {
      const currentCountries = response.data.countries;
      this.setState({ currentPage, currentCountries, totalPages });
    });
}

Sekarang, Anda dapat menyelesaikan komponen App dengan menambahkan metode render().

Dalam kelas App, tetapi setelah componentDidMount dan onPageChanged, tambahkan metode render berikut:

src/App.js
class App extends Component {
  // ... other methods here ...

  render() {
    const { allCountries, currentCountries, currentPage, totalPages } = this.state;
    const totalCountries = allCountries.length;

    if (totalCountries === 0) return null;

    const headerClass = ['text-dark py-2 pr-4 m-0', currentPage ? 'border-gray border-right' : ''].join(' ').trim();

    return (
      <div className="container mb-5">
        <div className="row d-flex flex-row py-5">
          <div className="w-100 px-4 py-5 d-flex flex-row flex-wrap align-items-center justify-content-between">
            <div className="d-flex flex-row align-items-center">
              <h2 className={headerClass}>
                <strong className="text-secondary">{totalCountries}</strong> Countries
              </h2>
              { currentPage && (
                <span className="current-page d-inline-block h-100 pl-4 text-secondary">
                  Page <span className="font-weight-bold">{ currentPage }</span> / <span className="font-weight-bold">{ totalPages }</span>
                </span>
              ) }
            </div>
            <div className="d-flex flex-row py-4 align-items-center">
              <Pagination totalRecords={totalCountries} pageLimit={18} pageNeighbours={1} onPageChanged={this.onPageChanged} />
            </div>
          </div>
          { currentCountries.map(country => <CountryCard key={country.cca3} country={country} />) }
        </div>
      </div>
    );
  }
}

Dalam metode render(), Anda merender jumlah total negara, halaman saat ini, jumlah total halaman, kontrol <Pagination>, kemudian <CountryCard> untuk setiap negara pada halaman saat ini.

Perhatikan bahwa Anda memberikan metode onPageChanged() yang Anda definisikan sebelumnya ke properti onPageChanged dari kontrol <Pagination>. Ini sangat penting untuk menangkap perubahan halaman dari komponen Pagination. Anda juga menampilkan 18 negara per halaman.

Di titik ini, aplikasi akan terlihat seperti tangkapan layar berikut:

Tangkapan Layar Aplikasi dengan 248 negara tercantum dan nomor halaman di atas untuk menggeser setiap halaman

Kini Anda memiliki komponen App yang menampilkan beberapa komponen CountryCard dan komponen Pagination yang memecah konten menjadi halaman yang terpisah. Selanjutnya, Anda akan menjelajahi penataan gaya dari aplikasi Anda.

Langkah 5 — Menambah Gaya Khusus

Anda mungkin telah memperhatikan bahwa Anda telah menambahkan beberapa kelas khusus pada komponen yang Anda ciptakan sebelumnya. Mari kita definisikan beberapa aturan gaya untuk kelas-kelas tersebut dalam berkas src/App.scss.

  1. nano src/App.scss

Berkas App.scss akan terlihat seperti cuplikan kode berikut:

src/App.scss
/* Declare some variables */
$base-color: #ced4da;
$light-background: lighten(desaturate($base-color, 50%), 12.5%);

.current-page {
  font-size: 1.5rem;
  vertical-align: middle;
}

.country-card-container {
  height: 60px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.country-name {
  font-size: 0.9rem;
}

.country-region {
  font-size: 0.7rem;
}

.current-page,
.country-name,
.country-region {
  line-height: 1;
}

// Override some Bootstrap pagination styles
ul.pagination {
  margin-top: 0;
  margin-bottom: 0;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);

  li.page-item.active {
    a.page-link {
      color: saturate(darken($base-color, 50%), 5%) !important;
      background-color: saturate(lighten($base-color, 7.5%), 2.5%) !important;
      border-color: $base-color !important;
    }
  }

  a.page-link {
    padding: 0.75rem 1rem;
    min-width: 3.5rem;
    text-align: center;
    box-shadow: none !important;
    border-color: $base-color !important;
    color: saturate(darken($base-color, 30%), 10%);
    font-weight: 900;
    font-size: 1rem;

    &:hover {
      background-color: $light-background;
    }
  }
}

Modifikasi berkas App.js Anda untuk merujuk ke App.scss alih-alih App.css.

Catatan: Untuk informasi lebih lanjut tentang ini, lihat dokumentasi Menciptakan Aplikasi React.

  1. nano src/App.js
src/App.js
import React, { Component } from 'react';
import Countries from 'countries-api';
import './App.scss';
import Pagination from './components/Pagination';
import CountryCard from './components/CountryCard';

Setelah menambahkan gaya, kini aplikasi akan terlihat seperti tangkapan layar berikut:

Tangkapan Layar Aplikasi halaman 1 dari 14, dengan Gaya

Kini Anda memiliki aplikasi yang lengkap dengan penataan gaya khusus tambahan. Anda dapat menggunakan gaya khusus untuk memodifikasi dan meningkatkan penataan gaya asali apa pun yang disediakan oleh pustaka seperti Bootstrap.

Kesimpulan

Dalam tutorial ini, Anda telah menciptakan widget paginasi khusus dalam aplikasi React. Meskipun Anda tidak membuat panggilan ke API atau berinteraksi dengan ujung belakang basis data apa pun dalam tutorial ini, aplikasi Anda mungkin menuntut interaksi tersebut. Anda tidak dibatasi dengan cara apa pun dalam hal pendekatan yang digunakan di tutorial ini - Anda dapat mengembangkannya sesuai keinginan untuk menyesuaikan keperluan aplikasi Anda.

Untuk kode sumber yang lengkap dari tutorial ini, lihat pagination-demorepositori [build-react-pagination-demo] di GitHub. Anda juga bisa mendapatkan demo langsung dari tutorial ini di Code Sandbox.

Jika Anda ingin mempelajari lebih lanjut tentang React, lihat seri Cara Melakukan Pengodean di React.js dari kami, atau baca halaman topik React kami untuk proyek pemrograman dan latihan.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Glad Chinda

author



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.