How to use React to set up Client-side Pagination using randomuser.API

·

6 min read

Assumes familiarity with React.JS and its extensions such as react-router, react-dom and Axios. However, if new to the world of React here is a quick view of how to get started.

Getting Started:

This page illustrates how to set up the React applications and some extensions needed for this pagination project.

let's get to it, shall we?

I guess YES LOL.

npx create-react-app my-app
cd my-app
npm start

On your terminal, enter the above commands to install and start your react app on your browser. The next line of actions shows us how to install the extensions needed such as the Axios, react-dom and react-router.

npm install axios
npm install --save react-router-dom

Good we've installed the necessary working tools, let's head to our VScode and see a view of how Display files should look after typing this line of command rfce to show the react functional hooks;

import React from "react";

function pagination(){
return(
<>

</>
)
}
export default display;

Now let's import the react hooks to this Display file;

import { useState, useEffect } from "react";

the above hooks are in-built into the React applications, let's move a step further by exporting the Display file to the root components called (App.js).

import Display from "./Display";
function App() {
  return (
    <>
    <Display />
    </>
)}

Alright, the root component has been updated by importing the Display file, we can go ahead to pass in our codes to the Display file.......Let's goooooo!!!!

Congratulations on coming this far, thumbs up;

Using the State hooks, hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.useState is a new way to use the same capabilities that this.state provides in a class. Normally, variables “disappear” when the function exits but state variables are preserved by React.

Step1-- We import the useState Hook from React. It lets us keep the local state in a function component as shown in the Images above.

 const [data, setData] = useState([]);
 const [loading, setLoading] = useState(false);

This might seem like a lot to take in at first. Don’t rush it! If you’re lost in the explanation, look at the code above again and try to read it from top to bottom or check the React documentation for further understanding.

next,

How to fetch data from APIs using Asynchronous await in ReactJS?

API: APIs are a type of application that stores data in the format of JSON (JavaScript Object Notation) and XML (Extensible Markup Language). It makes it possible for any device to talk to each other.

Asynchronous Await: Async ensures that the function returns a promise and wraps non-promises in it. There is another word Await, that works only inside the async function

 async function getData() {
    setLoading(true);
    const res = await fetch(`https://randomuser.me/api/`);
    try {
      const response = await res.json();
      const result = response.results;

      setData(result);
      setLoading(false);
    } catch (error) {
      console.log(error.message);
    }
  }

As an example, we would use the API Below; which would give us random data.

https://randomuser.me/api/

Async/Await is used to work with promises in asynchronous functions. It is syntactic sugar for promises. It is just a wrapper to restyle code and make promises easier to read and use. It makes asynchronous code look more like synchronous/procedural code, which is easier to understand.

Next, we implement the useEffects hooks,

Using the Effect Hook

By using this Hook, you tell React that your component needs to do something after rendering. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates.

in Summary, the Effect Hook lets you perform side effects in function components:

 useEffect(() => {
    getData();
  }, []);

Wow, we're almost there, now let's display our output in the return statement, now note that we must wrap our codes in react fragments or in div

 return (
    <div>

  </div>
); 
or
 return (
    <>

  </>);

wrap the codes in an inline-CSS codes

 <div
        style={{
          width: "100%",
          display: "flex",
          flexDirection: "column",
          justifyContent: "center",
        }}
      >
        {loading ? (
          <h1 className="load"> LOADING..</h1>
        ) : (
          data.map((item, idx) => {
            console.log(item);
            return <Card data={item} key={idx} />;
          })
        )}
        <div style={{ width: "15rem" }}>
          <Pagination
            UsersPerPage={1}
            currentPage={1}
            setCurrentPage={4}
            totalUsers={5}
          />
        </div>
      </div>

The pagination props in the render method above were passed down from this file

import React from "react";
import { Helmet } from "react-helmet-async";

function Pagination({ UsersPerPage, totalUsers, currentPage, setCurrentPage }) {
  const pageNumbers = [];

  for (
    let pageNumber = 1;
    pageNumber <= Math.ceil(totalUsers / UsersPerPage);
    pageNumber++
  ) {
    pageNumbers.push(pageNumber);
  }
  return (
    <nav className="page-numbers">
      {pageNumbers.map((pageNumber) => (
        <span
          key={pageNumber}
          onClick={() => {
            setCurrentPage(pageNumber);
          }}
          className="page-number"
          style={{
            color: currentPage === pageNumber ? "white" : "",
            backgroundColor: currentPage === pageNumber ? "black" : "",
          }}
        >
          {pageNumber}
        </span>
      ))}
    </nav>
  );
}

export default Pagination;

Here are the CSS codes for the pagination props;

  .page-numbers {
      display: flex;
      justify-content: space-between;
      margin: 30px auto;
      padding-left: 55px;
      width: 250px;
    }
    .page-number {
      font-family: "Raleway", sans-serif;
      cursor: pointer;
      display: flex;
      align-items: center;
      font-size: 15px;
      font-weight: bolder;
      justify-content: center;
      margin-right: 10px;
      border-radius: 3px;
      width: 200px;
      height: 40px;
      border-radius: 6px;
    }
    .load{
      margin-left: 100px;
      margin-top: 50px;
      font-family: "Raleway", sans-serif;
      font-size: 20px;
    }

import the CSS styles into the pagination files

import "../styles/Pagination.css";

After this follow-up, your pagination file should be looking nice as mine

import React from "react";
import "../styles/Pagination.css";

function Pagination({ UsersPerPage, totalUsers, currentPage, setCurrentPage }) {
  const pageNumbers = [];

  for (
    let pageNumber = 1;
    pageNumber <= Math.ceil(totalUsers / UsersPerPage);
    pageNumber++
  ) {
    pageNumbers.push(pageNumber);
  }
  return (
    <nav className="page-numbers">
      {pageNumbers.map((pageNumber) => (
        <span
          key={pageNumber}
          onClick={() => {
            setCurrentPage(pageNumber);
          }}
          className="page-number"
          style={{
            color: currentPage === pageNumber ? "white" : "",
            backgroundColor: currentPage === pageNumber ? "black" : "",
          }}
        >
          {pageNumber}
        </span>
      ))}
    </nav>
  );
}

export default Pagination;

Lastly, we need to export the card file to our Display file;

import React from "react";

const Card = ({ data }) => {
  return (
    <div className="card-section">
       <Helmet>
        <title>AltSchool</title>
        <meta name="description" content="AltSchool second semester Exam" />
        <link rel="canonical" href="/" />
       </Helmet>
      <div className="card-container">
        <div className="image-container">
          <img alt="Profile Pic" src={data.picture.medium} />
        </div>
        <div className="card-ctn">
          <div className="text">
            <div className="title">
              <h4>
                {data.name.title} {data.name.first} {data.name.last}
              </h4>
            </div>
            <p>{data.email}</p>
          </div>
          <div className="button">
            <button
              className="custom-btn"
              style={{ width: "6rem" }}
              onClick={() => {
                alert("Page Currently Unavailble");
              }}
            >
              View More
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Card;

Awesome!! our main Display page should be looking like this

import React, { useState, useEffect } from "react";
import Card from "./Card";
import Pagination from "./Pagination";
import {Helmet} from "react-helmet-async"
import { Link } from "react-router-dom";


function Display() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);

  async function getData() {
    setLoading(true);
    const res = await fetch(`https://randomuser.me/api/`);
    try {
      const response = await res.json();
      const result = response.results;
      // const info = response.info;
      setData(result);
      setLoading(false);
    } catch (error) {
      console.log(error.message);
    }
  }
  useEffect(() => {
    getData();
  }, []);
  return (
    <>
      <div
        style={{
          width: "100%",
          display: "flex",
          flexDirection: "column",
          justifyContent: "center",
        }}
      >
        {loading ? (
          <h1 className="load"> LOADING..</h1>
        ) : (
          data.map((item, idx) => {
            console.log(item);
            return <Card data={item} key={idx} />;
          })
        )}
        <div style={{ width: "15rem" }}>
          <Pagination
            UsersPerPage={1}
            currentPage={1}
            setCurrentPage={4}
            totalUsers={5}
          />
        </div>
      </div>
    </>
  );
}
export default Display;

Thanks for reading.