A Comprehensive Guide to React.js in 2018

<em>This article was originally published in January of 2015 but was recently updated to React 16.3 and all the goodness it contains.</em>

This article was originally published in January of 2015 but was recently updated to React 16.3 and all the goodness it contains.

React.js Fundamentals:

Components are the building blocks of React. If you’re coming from an Angular background, components are very similar to Directives. If you’re coming from a different background, they’re essentially widgets or modules. You can think of a component as a collection of HTML, CSS, JS, and some internal data specific to that component. I like to think of React components as the Kolaches of the web. They have everything you need, wrapped in a delicious composable bundle. These components are defined either in pure JavaScript or they can be defined in what the React team calls “JSX”. If you decide to use JSX (which you most likely will, it’s pretty standard — and it’s what we’ll use for this tutorial), you’ll need some compile stage to convert your JSX to JavaScript, we’ll get to this later.

What makes React so convenient for building user interfaces is that data is either received from a component’s parent component, or it’s contained in the component itself. Before we jump into code, let’s make sure we have a high level understanding of components.

Above we have a picture of my Twitter profile. If we were going to re-create this page in React, we would break different sections up into different components (highlighted). Notice that components can have nested components inside of them. We might name the left component (pink) the UserInfo component. Inside the UserInfo component we have another component (orange), that we could call the UserImages component. The way this parent/child relationship works is our UserInfo component, or the parent component, is where the ‘state’ of the data for both itself and the UserImages component (child component) lives. If we wanted to use any part of the parent component’s data in the child component, which we do, we would pass that data to the child component as an attribute. In this example, we pass the UserImages component all of the images that the user has (which currently live in the UserInfo component). We’ll get more into the details of the code in a bit, but I want you to understand the bigger picture of what’s happening here. This parent/child hierarchy makes managing our data relatively simple because we know exactly where our data lives and we shouldn’t manipulate that data anywhere else.

The topics below are what I believe to be the fundamental aspects of React. If you understand all of them and their purposes, you’ll be at a very good spot after reading this tutorial.

JSX — Allows us to write HTML like syntax which gets
transformed to lightweightJavaScript objects.

Virtual DOM — A JavaScript representation of the actual
DOM.

React.Component — The way in which you create a new component.

render (method) — Describes what the UI will look like for
the particular component.

ReactDOM.render — Renders a React component to a DOM node.

state — The internal data store (object) of a component.

constructor (this.state) - The way in which you establish
the initial state of a component.

setState — A helper method used for updating the state of a
component and re-rendering the UI

props — The data which is passed to the child component
from the parent component.

propTypes — Allows you to control the presence, or types of
certain props passed to the child component.

defaultProps — Allows you to set default props for your component.

Component LifeCycle

  • componentDidMount — Fired after the component mounted
  • componentWillUnmount — Fired before the component will unmount
  • getDerivedStateFromProps - Fired when the component mounts and
    whenever the props change. Used to update the state of a
    component when its props change

Events

  • onClick
  • onSubmit
  • onChange

I know it seems like a lot, but you’ll soon see how each piece is fundamental in building robust applications with React (and I also wasn’t kidding when I said I wanted this to be a comprehensive guide).

At this point you should understand, on a very high level, how React works. Now, let’s jump into some code.

Creating your First Component (JSX, Virtual DOM, render, ReactDOM.render)

Let's go ahead and build our very first React component.

To create a React component, you'll use an ES6 class. If you're not familiar with Classes, you can continue to read below or you can read more about them in depth here

import React from 'react'
import ReactDOM from 'react-dom'

class HelloWorld extends React.Component {
render() {
return (
<div>Hello World!</div>
)
}
}

ReactDOM.render(<HelloWorld />, document.getElementById('root'));

Notice that the only method on our class is render. Every component is required to have a render method. The reason for that is render is describing the UI (user interface) for our component. So in this example the text that will show on the screen where this component is rendered is Hello World! Now let's look at what ReactDOM is doing. ReactDOM.render takes in two arguments. The first argument is the component you want to render, the second argument is the DOM node where you want to render the component. (Notice we’re using ReactDOM.render and not React.render. This was a change made in React .14 to make React more modular. It makes sense when you think that React can render to more things than just a DOM element). In the example above we’re telling React to take our HelloWorld component and render it to the element with an ID of root. Because of the parent/child child relations of React we talked about earlier, you usually only have to use ReactDOM.render once in your application because by rendering the most parent component, all child components will be rendered as well.

Now at this point you might feel a little weird throwing “HTML” into your JavaScript. Since you started learning web development, you’ve been told that you should keep your logic out of the view, AKA keep your JavaScript uncoupled from your HTML. This paradigm is strong, but it does have some weaknesses. I don’t want to make this tutorial longer trying to convince you that this idea is a step in the right direction, so if this idea still bothers you you can check out this link. As you learn more about React, this uneasiness should quickly subside. The “HTML” that you’re writing in the render method isn’t actually HTML but it’s what React is calling “JSX”. JSX simply allows us to write HTML like syntax which (eventually) gets transformed to lightweight JavaScript objects. React is then able to take these JavaScript objects and from them form a “virtual DOM” or a JavaScript representation of the actual DOM. This creates a win/win situation where you get the accessibility of templates with the power of JavaScript.

Looking at the example below, this is what your JSX will eventually be compiled into.

class HelloWorld extends React.Component {
render() {
return React.createElement("div", null, "Hello World");
}
}
Now, you can forgo the JSX -> JS transform phase and write your React components
like the code above, but as you can imagine, that would be rather tricky. I’m
unaware of anyone who is not using JSX. For more information about what JSX compiles down to,
check out React Elements vs React Components

Up until this point we haven’t really emphasized the importance of this new virtual DOM paradigm we’re jumping into. The reason the React team went with this approach is because, since the virtual DOM is a JavaScript representation of the actual DOM, React can keep track of the difference between the current virtual DOM(computed after some data changes), with the previous virtual DOM (computed befores some data changes). React then isolates the changes between the old and new virtual DOM and then only updates the real DOM with the necessary changes. In more layman’s terms, because manipulating the actual DOM is slow, React is able to minimize manipulations to the actual DOM by keeping track of a virtual DOM and only updating the real DOM when necessary and with only the necessary changes. (More info here). Typically UI’s have lots of state which makes managing state difficult. By re-rendering the virtual DOM every time any state change occurs, React makes it easier to think about what state your application is in.

The process looks something like this,

Some user event which changes the state of your app → Re-render virtual DOM -> Diff previous virtual DOM with new virtual DOM -> Only update real DOM with necessary changes.

Because there’s this transformation process from JSX to JS, you need to set up some sort of transformation phase as you’re developing. In part 2 of this series I'll introduce Webpack and Babel for making this transformation.

Let’s take a look back at our “Most Important Parts of React” checklist and see where we’re at now.

<b>JSX — Allows us to write HTML like syntax which gets transformed
to lightweight JavaScript objects.</b>

<b>Virtual DOM — A JavaScript representation of the actual
DOM.</b>

<b>React.Component — The way in which you create a new component.</b>

<b>render (method) — Describes what the UI will look like for
the particular component.</b>

<b>ReactDOM.render — Renders a React component to a DOM node.</b>

state — The internal data store (object) of a component.

constructor (this.state) - The way in which you establish
the initial state of a component.

setState — A helper method used for updating the state of a
component and re-rendering the UI

props — The data which is passed to the child component
from the parent component.

propTypes — Allows you to control the presence, or types of
certain props passed to the child component.

defaultProps — Allows you to set default props for your component.

Component LifeCycle

  • componentDidMount — Fired after the component mounted
  • componentWillUnmount — Fired before the component will unmount
  • getDerivedStateFromProps - Fired when the component mounts and
    whenever the props change. Used to update the state of a
    component when its props change

Events

  • onClick

  • onSubmit

  • onChange

We’re making good pace. Everything in bold is what we’ve already covered and you

should at least be able to explain how those certain components fit into the

React ecosystem.

Adding State to your Component (state)

Next on the list is state. Earlier we talked about how managing user

interfaces is difficult because they typically have lots of different states.

This area is where React really starts to shine. Each component has the ability to manage its own state and pass its state down to child components if needed. Going back to the Twitter example from earlier, the UserInfocomponent (highlighted in pink above) is responsible for managing the state (or data) of the users information. If another component also needed this state/data but that state wasn’t a direct child of the UserInfo component, then you would create another component that would be the direct parent of the UserInfo and the other component (or both components which required that state), then you would pass the state down as props into the child components. In other words, if you have a multi component hierarchy, a common parent component should manage the state and pass it down to its children components via props.

Let’s take a look at an example component using it’s own internal state.

class HelloUser extends React.Component {
constructor(props) {
super(props)

this.state = {
username: 'tylermcginnis'
}
}
render() {
return (
<div>
Hello {this.state.username}
</div>
)
}
}

We’ve introduced some new syntax with this example. The first one you’ll notice is the constructor method. From the definition above, the constructor method is “The way in which you set the state of a component”. In other terms, any data you put on this.state inside of the constructor will be part of that component's state. In the code above we’re telling our component that we want it to keep track of a username. This username can now be used inside our component by doing {this.state.username}, which is exactly what we do in our render method.

The last thing to talk about with state is that our component needs the ability to modify its own internal state. We do this with a method called setState. Remember earlier when we talked about the re-rendering of the virtual dom whenever the data changes?

Signal to notify our app some data has changed→ Re-render virtual DOM -> Diff previous virtual DOM with new virtual DOM -> Only update real DOM with necessary changes.

That “signal to notify our app some data has changed” is actually just setState. Whenever setState is called, the virtual DOM re-renders, the diff algorithm runs, and the real DOM is updated with the necessary changes.

As a sidenote, when we introduce setState in the code below, we’re also going to introduce a few events that are on our list. Two birds, one stone.

So in the next code sample, we’re going to now have an input box that whenever someone types into it, it will automatically update our state and change the username.

class HelloUser extends React.Component {
constructor(props) {
super(props)

this.state = {
username: 'tylermcginnis'
}

this.handleChange = this.handleChange.bind(this)
}
handleChange (e) {
this.setState({
username: e.target.value
})
}
render() {
return (
<div>
Hello {this.state.username} <br />
Change Name:
<input
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
</div>
)
}
}

Note we’ve introduced a few more things. The first thing is the handleChange method. This method is going to get called every time a user types in the input box. When handleChange is called, it’s going to call setState to re-define our username withwhatever was typed into the input box (e.target.value). Remember, whenever setState is called, React creates a new virtual DOM, does the diff, then updates the real DOM.

Now let’s look at our render method. We’ve added a new line that contains an input field. The type of the input field is obviously going to be text. The value is going to be the value of our username which was originally defined in our getInitialState method and will be updated in the handleChangemethod. Notice there is a new attribute you’ve probably never seen before, onChange. onChange is a React thing and it will call whatever method you specify every time the value in the input box changes, in this case the method we specified was handleChange.

The process for the code above would go something like this.

A user types into the input box → handleChange is invoked → the state of our component is set to a new value → React re-renders the virtual DOM → React Diffs the change → Real DOM is updated.

Later on when we cover props, we’ll see some more advanced use cases of handling state.

We’re getting there! If you can’t explain the items in bold below, go re-read that section. One tip on REALLY learning React, don’t let passively reading this give you a false sense of security that you actually know what’s going on and can re-create what we’re doing. Head over to CodeSandbox and try to recreate (or create your own) components without looking at what I’ve done. It’s the only way you’ll truly start learning how to build with React. This goes for this tutorial and the following to come.

<b>JSX — Allows us to write HTML like syntax which gets transformed
to lightweight JavaScript objects.</b>

<b>Virtual DOM — A JavaScript representation of the actual
DOM.</b>

<b>React.Component — The way in which you create a new component.</b>

<b>render (method) — Describes what the UI will look like for the particular component.</b>

<b>ReactDOM.render — Renders a React component to a DOM node.</b>

<b>state — The internal data store (object) of a component.</b>

<b>constructor (this.state) - The way in which you establish the initial state of a component.</b>

<b>setState — A helper method used for updating the state of a
component and re-rendering the UI</b>

props — The data which is passed to the child component from the parent component.

propTypes — Allows you to control the presence, or types of certain props passed to the child component.

defaultProps — Allows you to set default props for your component.

Component LifeCycle

  • componentDidMount — Fired after the component mounted
  • componentWillUnmount — Fired before the component will unmount
  • getDerivedStateFromProps - Fired when the component mounts and
    whenever the props change. Used to update the state of a
    component when its props change

Events

  • onClick
  • onSubmit
  • onChange

Receiving State from Parent Component (props, propTypes, getDefaultProps)

We’ve talked about props a few times already since it’s hard to really do much without them. By our definition above, props is the data which is passed to the child component from the parent component. This allows for our React architecture to stay pretty straight forward. Handle state in the highest most parent component which needs to use the specific data, and if you have a child component that also needs that data, pass that data down as props.

Here’s a very basic example of using props.

class HelloUser extends React.Component {
render() {
return (
<div> Hello, {this.props.name}</div>
)
}
}

ReactDOM.render(<HelloUser name="Tyler"/>, document.getElementById('root'));

Notice on line 9 we have an attribute called name with a value of “Tyler”. Now in our component, we can use {this.props.name} to get “Tyler”.

Let’s look at a more advanced example. We’re going to have two components now. One parent, one child. The parent is going to keep track of the state and pass a part of that state down to the child as props. Let’s first take a look at that parent component.

Parent Component:

class FriendsContainer extends React.Component {
constructor(props) {
super(props)

this.state = {
  name: 'Tyler McGinnis',
  friends: ['Jake Lingwall', 'Sarah Drasner', 'Merrick Christensen']
}

}
render() {
return (
<div>
<h3> Name: {this.state.name} </h3>
<ShowList names={this.state.friends} />
</div>
)
}
}

There really isn’t much going on in this component that we haven’t seen before. We have an initial state and we pass part of that initial state to another component. The majority of the new code will come from this child component so let’s take a closer look at that.

Child Component:

class ShowList extends React.Component {
render() {
return (
<div>
<h3> Friends </h3>
<ul>
{this.props.names.map((friend) => <li>{friend}</li>)}
</ul>
</div>
)
}
}

Remember that the code that gets returned from our render method is a representation of what the real DOM should look like. If you’re not familiar with Array.prototype.map, this code might look a little wonky. All map does is it creates a new array, calls our callback function on each item in the array, and fills the new array with the result of calling the callback function on each item. For example,

const friends = ['Jake Lingwall', 'Sarah Drasner', 'Merrick Christensen'];
const listItems = friends.map((friend) => {
return "<li> " + friend + "</li>";
});

console.log(listItems);
// ["<li> Jake Lingwall</li>", "<li> Sarah Drasner</li>", "<li> Merrick Christensen</li>"];

The console.log above returns 


["<li> Jake Lingwall</li>", "<li> Murphy

Randall</li>", "<li> Merrick Christensen</li>"]


.

Notice all that happened was we

made a new array and added 


<li> </li>


to each item in the original array.

What’s great about map is it fits perfectly into React (and it’s built into JavaScript). So in our child component above, we’re mapping over names, wrapping each name in a pair of 

 tags, and saving that to our listItems variable. Then, our render method returns an unordered list with all of our friends.

Let’s look at one more example before we stop talking about props. It’s important to understand that wherever the data lives, is the exact place you want to manipulate that data. This keeps it simple to reason about your data. All getter/setter method for a certain piece of data will always be in the same component where that data was defined. If you needed to manipulate some piece of data outside where the data lives, you’d pass the getter/setter method into that component as props. Let’s take a look at an example like that.

class FriendsContainer extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      name: 'Tyler McGinnis',
      friends: [
        'Jake Lingwall',
        'Sarah Drasner',
        'Merrick Christensen'
      ],
    }

    this.addFriend = this.addFriend.bind(this)
  }
  addFriend(friend) {
    this.setState((state) =&gt; ({
      friends: state.friends.concat([friend])
    }))
  }
  render() {
    return (
      &lt;div&gt;
        &lt;h3&gt; Name: {this.state.name} &lt;/h3&gt;
        &lt;AddFriend addNew={this.addFriend} /&gt;
        &lt;ShowList names={this.state.friends} /&gt;
      &lt;/div&gt;
    )
  }
}
</pre><blockquote>🚨. Notice that in our addFriend method we introduced a new way to invoke setState. Instead of passing it an object, we're passing it a function which is then passed&nbsp;state. Whenever you're setting the new state of your component based on the previous state (as we're doing with our friends array), you want to pass setState a function which takes in the current state and returns the data to merge with the new state.</blockquote><pre class="ql-syntax" spellcheck="false">class AddFriend extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      newFriend: ''
    }

    this.updateNewFriend = this.updateNewFriend.bind(this)
    this.handleAddNew = this.handleAddNew.bind(this)
  }
  updateNewFriend(e) {
    this.setState({
      newFriend: e.target.value
    })
  }
  handleAddNew() {
    this.props.addNew(this.state.newFriend)
    this.setState({
      newFriend: ''
    })
  }
  render() {
    return (
      &lt;div&gt;
        &lt;input
          type="text"
          value={this.state.newFriend}
          onChange={this.updateNewFriend}
        /&gt;
        &lt;button onClick={this.handleAddNew}&gt; Add Friend &lt;/button&gt;
      &lt;/div&gt;
    )
  }
}
class ShowList extends React.Component {
  render() {
    return (
      &lt;div&gt;
        &lt;h3&gt; Friends &lt;/h3&gt;
        &lt;ul&gt;
          {this.props.names.map((friend) =&gt; {
            return &lt;li&gt; {friend} &lt;/li&gt;
          })}
        &lt;/ul&gt;
      &lt;/div&gt;
    )
  }
}
</pre><p>You’ll notice the code above is mostly the same as the previous example, except now we have the ability to add a name to our friends list. Notice how I created a new AddFriend component that manages the new friend we’re going to add. The reason for this is because the parent component (FriendContainer) doesn’t care about the new friend you’re adding, it only cares about all of your friends as a whole (the friends array). However, because we’re sticking with the rule of only manipulate your data from the component that cares about it, we’ve passed the addFriend method down into our AddFriend component as a propand we call it with the new friend once the handleAddNew method is called.</p><p>At this point I recommend you try to recreate this same functionality on your own using the code above as a guidance once you’ve been stuck for 3-4 minutes.</p><p>Before we move on from props, I want to cover two more React features regarding props. They are&nbsp;<strong>propTypes</strong>&nbsp;and&nbsp;<strong>defaultProps.</strong>&nbsp;I won’t go into too much detail here because both are pretty straight forward.</p><p><strong>prop-types</strong>&nbsp;allow you to control the presence, or types of certain props passed to the child component. With propTypes you can specify that certain props are required or that certain props be a specific type.</p><blockquote>As of React 15, PropTypes is no longer included with the React package. You'll need to install it separately by running&nbsp;npm install prop-types.</blockquote><p><strong>defaultProps</strong>&nbsp;allow you to specify a default (or a backup) value for certain props just in case those props are never passed into the component.</p><p>I’ve modified our components from earlier to now, using propTypes, require that addFriend is a function and that it’s passed into the AddFriend component. I’ve also, using defaultProps, specified that if no array of friends is given to the ShowList component, it will default to an empty array.</p><pre class="ql-syntax" spellcheck="false">import React from 'react'
import PropTypes from 'prop-types'

class AddFriend extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      newFriend: ''
    }
  }
  updateNewFriend(e) {
    this.setState({
      newFriend: e.target.value
    })
  }
  handleAddNew() {
    this.props.addNew(this.state.newFriend)
    this.setState({
      newFriend: ''
    })
  }
  render() {
    return (
      &lt;div&gt;
        &lt;input type="text" value={this.state.newFriend} onChange={this.updateNewFriend} /&gt;
        &lt;button onClick={this.handleAddNew}&gt; Add Friend &lt;/button&gt;
      &lt;/div&gt;
    )
  }
}

AddFriend.propTypes: {
  addNew: PropTypes.func.isRequired
}
class ShowList extends React.Component {
  render() {
    return (
      &lt;div&gt;
        &lt;h3&gt; Friends &lt;/h3&gt;
        &lt;ul&gt;
          {this.props.names.map((friend) =&gt; {
            return &lt;li&gt; {friend} &lt;/li&gt;
          })}
        &lt;/ul&gt;
      &lt;/div&gt;
    )
  }
}

ShowList.defaultProps = {
  names: []
}
</pre><p>Alright, we’re on the last stretch for this first tutorial. Let’s take a look at</p><p>our guide and see what we have left.</p><pre class="ql-syntax" spellcheck="false">&lt;b&gt;JSX — Allows us to write HTML like syntax which gets transformed
to lightweight JavaScript objects.&lt;/b&gt;

&lt;b&gt;Virtual DOM — A JavaScript representation of the actual
DOM.&lt;/b&gt;

&lt;b&gt;React.Component — The way in which you create a new component.&lt;/b&gt;

&lt;b&gt;render (method) — Describes what the UI will look like for
the particular component.&lt;/b&gt;

&lt;b&gt;ReactDOM.render — Renders a React component to a DOM node.&lt;/b&gt;

&lt;b&gt;state — The internal data store (object) of a component.&lt;/b&gt;

&lt;b&gt;constructor (this.state) - The way in which you establish
the initial state of a component.&lt;/b&gt;

&lt;b&gt;setState — A helper method used for updating the state of a
component and re-rendering the UI&lt;/b&gt;

&lt;b&gt;props — The data which is passed to the child component
from the parent component.&lt;/b&gt;

&lt;b&gt;prop-types — Allows you to control the presence, or types of
certain props passed to the child component.&lt;/b&gt;

&lt;b&gt;defaultProps — Allows you to set default props for your component.&lt;/b&gt;

Component LifeCycle
  - componentDidMount — Fired after the component mounted
  - componentWillUnmount — Fired before the component will unmount
  - getDerivedStateFromProps - Fired when the component mounts and
whenever the props change. Used to update the state of a
component when its props change

&lt;b&gt;Events
  - onClick
  - onSubmit
  - onChange
&lt;/b&gt;
</pre><p>We’re so close!</p><p><strong>Component LifeCycle</strong></p><p>Each component you make will have its own lifecycle events that are useful for various things. For example, if we wanted to make an ajax request on the initial render and fetch some data, where would we do that? Or, if we wanted to run some logic whenever our props changed, how would we do that? The different lifecycle events are the answers to both of those. Let’s break them down.</p><pre class="ql-syntax" spellcheck="false">class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      name: 'Tyler McGinnis'
    }
  }
  componentDidMount(){
    // Invoked once the component is mounted to the DOM
    // Good for making AJAX requests
  }
  static getDerivedStateFromProps(nextProps, prevState) {
    // The object you return from this function will
    // be merged with the current state.
  }
  componentWillUnmount(){
    // Called IMMEDIATELY before a component is unmounted
    // Good for cleaning up listeners
  }
  render() {
    return (
      &lt;div&gt;
        Hello, {this.state.name}
      &lt;/div&gt;
    )
  }
}
</pre><p><strong>componentDidMount</strong>&nbsp;- Invoked once after the initial render. Because the component has already been invoked when this method is invoked, you have access to the virtual DOM if you need it. You do that by calling&nbsp;<strong>this.getDOMNode()</strong>. So this is the lifecycle event where you’ll be making your AJAX requests to fetch some data.*</p><p><strong>componentWillUnmount</strong>&nbsp;- This life cycle is invoked immediately before a component is unmounted from the DOM. This is where you can do necessary clean up.</p><p><strong>getDerivedStateFromProps</strong>&nbsp;- Sometimes you'll need to update the state of your component based on the props that are being passed in. This is the lifecycle method in which you'd do that. It'll be passed the props and the state, and the object you return will be merged with the current state.</p><p>Well, if you stuck with me until this point, great job. I hope this tutorial was beneficial to you and you now feel at least mildly comfortable with React.</p><blockquote>For a much more in depth look at the fundamentals of React, check out our&nbsp;<a href="https://tylermcginnis.com/courses/react-fundamentals/" target="_blank">React Fundamentals</a>&nbsp;course.</blockquote><p><br></p><h3>By : <a href="https://dev.to/tylermcginnis" target="_blank">Tyler McGinnis</a></h3><p><br></p>

Pagination in ReactJs

Pagination in ReactJs

There are a lot of resourceful materials online that give good insights into pagination in ReactJs, as well as NPM packages you can easily use

There are a lot of resourceful materials online that give good insights into pagination in ReactJs, as well as NPM packages you can easily use. As much as I appreciate those materials and love to use those packages, they mostly deal with loading the whole dataset on the page first then completely handle the pagination in the frontend. I am approaching this article with the concept of loading the exact data needed on the page, then manually loading other dataset based on the request when the user clicks the pagination number display. Below is the content structure to guide us through this article:

Table of Contents
  • Project Setup
  • HTML and CSS Styling
  • Pagination Data Format
  • Sample API request
  • Displaying the initial data
  • Showing Page Number and getting Other data
Project Setup

We are going to use create-react-app v0.1.0 which has the CSS Module configured already. Open your terminal and cd to the folder you want the project installed. Then run the below command:

npx create-react-app pagination  --use-npm

The above command will download the project into the folder calledpagination. You need to cd into the folder and run npm start. If everything goes well, you will have a page that looks like below:

HTML and CSS Styling

Open the project in your favorite code editor and locate the App.js file, We need to prepare our App.js to the look exactly like the way we want it by adding the HTML code and CSS style below:

Create a new file called App.module.css in the same directory where you have your App.js, then import it into your App.js using:

import styles from './App.module.css';

I want us to handle the display of the pagination number first, below is the style and HTML structure of what we are going to use.

  render() {
    

    return (
      <div className={styles.app}>
        
        <table className={styles.table}>
          <thead>
            <tr>
              <th>S/N</th>
              <th>First Name</th>
              <th>Last Name</th>
            </tr>
          </thead>
          <tbody>
              <tr>
                <td>1</td>
                <td>Abel</td>
                <td>Agoi</td>
              </tr>
              <tr>
                <td>2</td>
                <td>Muyiwa</td>
                <td>Aregbesola</td>
              </tr>
              <tr>
                <td>3</td>
                <td>Opeyemi</td>
                <td>Agoi</td>
              </tr>
              <tr>
                <td>4</td>
                <td>Ope</td>
                <td>Aina</td>
              </tr>
          </tbody>
        </table>


        <div className={styles.pagination}>
          <span>&laquo;</span>
          <span className={styles.active}>1</span>
          <span>2</span>
          <span>3</span>
          <span>4</span>
        </div>

      </div>
    );
  }

pagination_01.js

Add the content below into your App.module.css.

.app {
    width: 50%;
    margin: 0 auto;
}

table {
  border-collapse: collapse;
  border-spacing: 0; 
}


table {
  border-collapse: separate;
  border-spacing: 0;
  color: #4a4a4d;
  font: 14px/1.4 "Helvetica Neue", Helvetica, Arial, sans-serif;
  width: 100%;
}
tr {
  overflow-x: scroll;
}
th,
td {
  padding: 15px 15px;
  vertical-align: middle;
  /* text-align: left; */
}
thead {
  font-size: 14px;
  line-height: 24px;
  font-family: Lato;
  border: 1px solid transparent;

  max-width: 100%;
  font-weight: 900;
  line-height: 24px;
  mix-blend-mode: normal;

  color: rgba(51, 51, 51, .5);
  background: rgba(255, 255, 255, .9);
}
thead tr th {
  padding: 15px 15px;
  border: 1px solid transparent;


  text-align: left;
}
tbody {
  max-width: 100%;
}
tbody tr:nth-child(odd) {
  background: #f0f0f2;
}
tbody tr:hover {
  background: #f0f0f2;
}
td {
  padding: 15px 15px;
}
td:first-child {
}


.pagination {
    margin-top: 25px;
}
.pagination span {
  cursor: pointer;
  color: black;
  float: left;
  padding: 8px 16px;
  text-decoration: none;
  transition: background-color .3s;
  border: 1px solid #ddd;
}

.pagination span.active {
  background-color: #0099FF;
  color: white;
  border: 1px solid #0099FF;
}

pagination_app.module.css

Sorry for the plenty code written so far :), I want us to have a good looking table with pagination style in place before we move into the actual paging. If everything goes well, your view should look like below:

Pagination Data Format

In most cases, when you are making API calls to an endpoint that returns a paginated data, you need to pass at least the page number with the URL, hence a sample URL will look like below:

https://reqres.in/api/users?page=2

The most important thing to take note of in the URL above is the page=2 where 2 is the page number dataset we want to get. It can be 3,4 or any number as much as the dataset we have in the backend.

The response will always contain three important data which are per_page, total and the actual data we want to loop through. A sample response looks like below:

Sample API request

Talking about making an API request to the backend, We need a backend to make the request to, I decide to use https://reqres.in/ as the API endpoint for this tutorial because it is free, always available and reliable. You can decide to make your API request directly inside your component’s ComponentDidMount() or dispatch an action to redux from your ComponentDidMount() but for the purpose of this tutorial, we are going to make the API call from the App.js componentDidMount().

Firstly, we need to set the component’s state like below inside your App.js

  state = {
    users: null,
    total: null,
    per_page: null,
    current_page: null
  }

pagination_component_state.js

users is going to be the data we are going to loop over, while total and per_page is going to help us with calculating paging logic while the current_page will be used to style the active pagination link.

The next thing we should do is create a helper method that will serve the purpose of making an HTTP request to the API endpoint and also update the state with the response data. The method will look like below:

  makeHttpRequestWithPage = async pageNumber => {
    let response = await fetch(`https://reqres.in/api/users?page=${pageNumber}`, {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
    });

    const data = await response.json();

    this.setState({
      users: data.data,
      total: data.total,
      per_page: data.per_page,
      current_page: data.page,
    });
  }

pagination_http_request.js

This method will accept a parameter called pageNumber so it can be reusable and will always update the state with the right data when the response is successful.

Since on page load, we need to make the HTTP request to the backend, and we are going to do this inside thecomponentDidMount() by calling the method above and passing it the first-page number we want which should be 1. Hence, the componentDidMount() will look like below:

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

pagination_componentDidMount.js

If we add console.dir(this.state.users) inside the render() method, below will be printed in the console

The null was before the data arrived, once the data arrived, it updates the state, hence the array of users data.

Displaying the initial data

Haven gotten the data needed, we need to loop through the data and display it. Hence we can update our render method to have below:

    let users;

    if (this.state.users !== null) {
      users = this.state.users.map(user => (
        <tr key={user.id}>
          <td>{user.id}</td>
          <td>{user.first_name}</td>
          <td>{user.last_name}</td>
        </tr>
      )); 
    }
    
    return (
      <div className={styles.app}>
        
        <table className={styles.table}>
          <thead>
            <tr>
              <th>S/N</th>
              <th>First Name</th>
              <th>Last Name</th>
            </tr>
          </thead>
          <tbody>
              { users }
          </tbody>
        </table>


        <div className={styles.pagination}>
          <span>&laquo;</span>
          <span className={styles.active}>1</span>
          <span>2</span>
          <span>3</span>
          <span>4</span>
          <span>&raquo;</span>
        </div>

      </div>
    );

gistfile1.txt

I replaced the dummy data we had inside the with the result of the loop which I equated to users. We have the assurance that when the state changes, ReactJs will automatically update the content of the table. The final stage is displaying the page logic and getting the other contents based on the page number clicked which will be sent to the API endpoint.

Showing Page Number and getting other data

Before we talk about showing page number automatically using the desired logic, I want us to manually show those numbers and make the actual API calls when the numbers are clicked. For now, we are going to hard code the pagination numbers ourselves like below:

<div className={styles.pagination}>
  <span onClick={() => this.makeHttpRequestWithPage(1)}>1</span>
  <span onClick={() => this.makeHttpRequestWithPage(2)}>2</span>
  <span onClick={() => this.makeHttpRequestWithPage(3)}>3</span>
  <span onClick={() => this.makeHttpRequestWithPage(4)}>4</span>
</div>

pagination_hard_code.js

The above code will look like below when previewed in the browser.

Notice that each span has an event handler attached to it, and I passed the page number to that event handler, so anytime we click on the pagination link, it will make a new HTTP request and update the component states, hence the user’s table data. We do not want to hard-code the links as we did above, so we need to automatically display those links.

So we’re planning on showing the page numbers for a series of pieces of data so that users can easily navigate multiple items. There are a few things that we need to know first:

  • The page that we’re on
  • Total number of items
  • Number of items per page

Good news is that we have captured all these things in our component’s state.

Next, we need to look at how we want to display the page numbers, there is a wide range of methods that people use:

  • Simple Next/Previous buttons with no numbers
  • A list of all possible pages
  • Page 1 & the last page, with the current page (and 2 above/below) shown

I personally prefer to show the very first page, that last page, and then the current page with 2 pages above & below. So for example on page 12 out of 24 pages we’d see:

1, 10, 11, 12, 13, 14, 24

This allows users to quickly navigate to the start, and to the end, as well as jump through multiple pages at once. For the purpose of this tutorial, I am going to show us how to show a list of all possible pages(item two above) then item three too.

The Arithmetic

We need to work out the total number of pages, for this, we want to take the total number of items that there are, and divide it by the number of items per page. But we want to make sure that we take that number and round it up.

So if there were 12 items in total, and we were showing 5 per page, we’d have a total of 3 pages of items. If we were to show 3 per page, we’d show 4 pages.

const pageNumbers = [];
for (let i = 1; i <= Math.ceil(this.state.meta.total / this.state.meta.per_page); i++) {
    pageNumbers.push(i);
}

page_logic_pagination.js

Haven gotten the page numbers, we need to loop through to display the span since we want to show all possible numbers first, our loop will look like below:

renderPageNumbers = pageNumbers.map(number => {
  let classes = this.state.current_page === number ? styles.active : '';

  return (
    <span key={number} className={classes} onClick={() => this.makeHttpRequestWithPage(number)}>{number}</span>
  );
});

pagination_all_numbers_loop.js

We need to update our pagination view to look like below:

<div className={styles.pagination}>
  <span onClick={() => this.makeHttpRequestWithPage(1)}>&laquo;</span>
  {renderPageNumbers}
</div>

pagination_view._01js

Congrats, we have successfully handle pagination, make HTTP request to the backend and changing the table content when user click on the page number to see.

To be sure we are on the same page, my App.js code looks like below:

import React, { Component } from 'react';
import styles from './App.module.css';

class App extends Component {


  state = {
    users: null,
    total: null,
    per_page: null,
    current_page: 1
  }


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


  makeHttpRequestWithPage = async pageNumber => {
    const response = await fetch(`https://reqres.in/api/users?page=${pageNumber}`, {
      method: 'GET',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
    });

    const data = await response.json();

    this.setState({
      users: data.data,
      total: data.total,
      per_page: data.per_page,
      current_page: data.page
    });
  }


  render() {

    let users, renderPageNumbers;

    if (this.state.users !== null) {
      users = this.state.users.map(user => (
        <tr key={user.id}>
          <td>{user.id}</td>
          <td>{user.first_name}</td>
          <td>{user.last_name}</td>
        </tr>
      ));
    }

    const pageNumbers = [];
    if (this.state.total !== null) {
      for (let i = 1; i <= Math.ceil(this.state.total / this.state.per_page); i++) {
        pageNumbers.push(i);
      }


      renderPageNumbers = pageNumbers.map(number => {
        let classes = this.state.current_page === number ? styles.active : '';

        return (
          <span key={number} className={classes} onClick={() => this.makeHttpRequestWithPage(number)}>{number}</span>
        );
      });
    }

    return (


      <div className={styles.app}>

        <table className={styles.table}>
          <thead>
            <tr>
              <th>S/N</th>
              <th>First Name</th>
              <th>Last Name</th>
            </tr>
          </thead>
          <tbody>
            {users}
          </tbody>
        </table>


        <div className={styles.pagination}>
          <span onClick={() => this.makeHttpRequestWithPage(1)}>&laquo;</span>
          {renderPageNumbers}
          <span onClick={() => this.makeHttpRequestWithPage(1)}>&raquo;</span>
        </div>

      </div>
    );
  }

}

export default App;

pagination_app.js

and my view like below:

We can change the page number display logic to below since it will accommodate for large dataset.

renderPageNumbers = pageNumbers.map(number => {
  let classes = this.state.current_page === number ? styles.active : '';

  if (number == 1 || number == this.state.total || (number >= this.state.current_page - 2 && number <= this.state.current_page + 2)) {
    return (
      <span key={number} className={classes} onClick={() => this.makeHttpRequestWithPage(number)}>{number}</span>
    );
  }
});

pagination_another_display_logic.js

Thanks for reading.

URLs and Webpack in Reactjs

URLs and Webpack in Reactjs

URLs and Webpack in Reactjs - I am still a newbie in ReactJS. I've been following series of tutorials and articles on the framework and decided to start putting what I've learnt so far into practice.

My website, dillionmegida.com was built with PHP. You could check it out as I highly appreciate reviews. I'm though aspiring to be a full-stack javascript developer so I'm in some way trying to depart from PHP :)

I decided to replicate my homepage using React and to broaden my skills in using components.

It was going quite successful until I tried using an <img> JSX element. I used it like;

import React from 'react'
 
let dpStyle = {
    // Some styles
}
 
let Profilepic = () => (
    <div className={dpStyle}>
        <img src='../img/deee.jpeg' alt='My profile picture'/>
    </div>
)
export default Profilepic;

The img folder was a sub-directory of the src folder.

My aim here was to have my profile picture as a component with some styling to be used on my homepage and any other desired page. The src for the img tag was not been used appropriately as my image was not displayed.

I paused to think of the problem, inspected my page and discovered the src displayed there was exactly as I inputted it. So silly of me :( I made some researches which helped me remember that most attributes of JSX element are not as mostly used with HTML, but have to be enclosed in curly braces.

import React from 'react'
 
let dpStyle = {
    // Some styles
}
 
let Profilepic = () => (
    <div className={dpStyle}>
        <img src={'../img/deee.jpeg'} alt='My profile picture'/>
    </div>
)
export default Profilepic;

I tried rendering the page again and my image was still not displayed.

Funny enough, I quickly thought of a trick (for the first time);

...
import Dp from '../img/deee.jpeg'
...
let Profilepic = () => (
    <div className={dpStyle}>
        <img src={Dp} alt='My profile picture'/>
    </div>
)

To my amazement, it worked. I was excited and at the same time sad, with feeling of little guilt. I didn't know why. lol. I said to myself, 'I am not doing the right thing :(' and also asked myself, 'Is react as crazy as this?'

I headed back to google to make some more research and got to discover that the webpack that React (create-react-app) automatically installed had been configured to use the public folder (at the same level with src folder) for relative URLs (such as my image URL).

Using ...<img src={'../img/deee.jpeg'} />..., React was actually checking the public folder for the image sub-directory which it couldn't find.

Solution

1. Change the location of the image folder

I changed the location of the image folder making it a sub-directory under the public directory and it worked as expected.

2. Use the require keyword

Just as the import keyword is used for relative URLs, the require keyword does same. So, I was able to do this;

import React from 'react'
 
let dpStyle = {
    // Some styles
}
 
let Profilepic = () => (
    <div className={dpStyle}>
        <img src={require('../img/deee.jpeg')} alt='My profile picture'/>
    </div>
)
export default Profilepic;

and in the other pages where the Profilepic component was required and used, my image displayed perfectly. :D

Like I said, I am still a newbie at ReactJS but I hope this little experience would be helpful for you too. There are other super powers of webpacks too which I would still be learning. Please do share in the comment section corrections on this article and also helpful Tips.

I'll be documenting my experience in my ReactJS journey as much as I can. Stay tuned and thanks for reading.

Originally published by Megida Dillion at dillion.hashnode.dev

=======================================================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ Understanding TypeScript

☞ Typescript Masterclass & FREE E-Book

☞ React - The Complete Guide (incl Hooks, React Router, Redux)

☞ Modern React with Redux [2019 Update]

☞ The Complete React Developer Course (w/ Hooks and Redux)

☞ React JS Web Development - The Essentials Bootcamp

☞ React JS, Angular & Vue JS - Quickstart & Comparison

☞ The Complete React Js & Redux Course - Build Modern Web Apps

☞ React JS and Redux Bootcamp - Master React Web Development