Pagination | Rails — React — Redux
There is no denying that as programmers, space and time are a major concern when building scalable applications. Take a moment to think about a website such as Amazon. When you search for a product you might get back 10,000+ results, however only a select number of products are truly rendered. This isn’t because Amazon has some personal vendetta against allowing users to view all results on one page, it just wouldn’t be practical. This is where pagination comes into play.
What’s pagination?
Pagination is the process of limiting how much data is actually being sent. This also means knowing what information belongs to which page, and which page the user is currently on. This way, instead of loading all of our results, we might only load 30 products on one page, then the following 30 products would be loaded on the next page, and so on. I think you get the gist, let’s get to implementing!
— Backend
We will start by configuring our backend
Gemfile
We’re first going to add the will_paginate gem to our Gemfile
gem 'will_paginate'
The will_paginate gem will gives us a few methods which will do a majority of the backend work for us!
Model
In your model, you will want to define self.per_page
This is how many objects you would like to display per page, in my case 3
class Studio < ApplicationRecordhas_many :reviewshas_many :users, through: :reviewsself.per_page = 3end
Controller
We will need to update our index action to the following in order to correctly paginate our output as an API
class StudiosController < ApplicationControllerdef index@studios = Studio.paginate(:page => params[:page]render json: @studiosendend
In addition, we will also need to display what page is associated to the given data, as well as the total number of pages. This is where will_paginate
comes in handy
class StudiosController < ApplicationControllerdef index@studios = Studio.paginate(:page => params[:page]render json: {
studios: @studios,
page: @studios.current_page,
pages: @studios.total_pages
}endend
— Frontend
Let’s import the Semantic UI pagination bar to eliminate the need to construct one ourselves
Place your import at the top of whatever component you’re rendering it from
import { Pagination } from 'semantic-ui-react';
You’ll also need to place the Pagination element in your return
<PaginationonPageChange={ handlePage }size="mini"siblingRange="1"defaultActivePage={ page }totalPages={ pages }/>
onPageChange
Will contain a function to handle the changing of pages
siblingRange
How many pages left and right of current page
defaultActivePage
The current page
totalPages
Total amount of pages
Creating the handlePage function
Inside of our component, but outside of the return function, is where we will place our handlePage
function
import { useDispatch } from 'react-redux';const handlePage = (e, { activePage }) => {let goToPage = { activePage };let pageNum = goToPage.activePage;let pageString = pageNum.toString();const url = "http://localhost:3000/studios/?page=" + pageString;fetch(url).then(res => res.json()).then(data => dispatch({type: "SET_STUDIOS",payload: data}));}
What this function does is fetches page results from our Rails API depending on the current page. It well then dispatch an action which I’ve labeled here as “SET_STUDIOS”
which we will add in our action creators
export const setStudios = () => {return dispatch => {fetch(API + "/studios").then(res => res.json()).then(data => dispatch({type: "SET_STUDIOS",payload: data}))}}
This is a basic index action creator which you may already have configured into your application
Let’s also account for this in our reducer
const initialState = {studios: {studios: [],page: 1,page_count: 1}}const studiosReducer = (state=initialState, action) => {switch (action.type){case "SET_STUDIOS":return {...state, studios: action.payload}}}default:return {...state}}}
Congrats!
You should now have a fully functioning pagination bar!