DEV Community

Cover image for Implementing react-select Async with React Hooks and applying Pagination
Helmar Junior
Helmar Junior

Posted on

Implementing react-select Async with React Hooks and applying Pagination

This tutorial is about implementing the React Component react-select with Async AJAX request and pagination applied. As we won't implement the BackEnd code, we can just use the OpenSource API: https://www.anapioficeandfire.com/api

Very often we need to create a Select Dropdown for our React application. It will be populated dynamically with information from the database and the AJAX endpoint can be changed based on another React State.

For example: You need to load the street names of a city. So in this case, when the city property change, a new AJAX request needs to be made to populate the Select Dropdown with the new options. But what happens if the backend returns hundreds (or thousands) of street names? It will overload the BackEnd and FrontEnd. To avoid overloading the best practice is to apply request pagination to show certain number of options as the user needs.

Installing required components:

React-Select is extremely easy to use dropdown library exclusively built for React. The react-select library offers powerful multi-select, autocomplete, and AJAX support without any hassle. React-select’s main power lies in its dynamic functionalities such as search, filter, async loading, animated component, easy accessibility, and faster loading time. npm install react-select

react-select-async-paginate - wrapper above react-select that supports pagination on menu scroll. npm install react-select-async-paginate

First clean the App.js up and implement the Static Options Select that will update the State and reload the Async Select:

import React, { useState } from 'react';
import Select from "react-select";

const App = () => {
   const options = [
       { value: "The Crownlands" },
       { value: "Iron Islands" },
       { value: "The North" },
       { value: "The Reach" },
       { value: "The Riverlands" },
       { value: "The Vale" },
       { value: "The Westerlands" },
       { value: "The Stormlands" }
   ];
  const [region, setRegion] = useState(options[0]);
  const [currentCountry, setCurrentCountry] = useState(null);
  const onchangeSelect = (item) => {
    setCurrentCountry(null);
    setRegion(item);
  };
  return (
    <div className="App">
       <Select
          value={region}
          onChange={onchangeSelect}
          options={options}
          getOptionValue={(option) => option.value}
          getOptionLabel={(option) => option.value}
       />
    </div>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

Second, let's create a new file SelectAsyncPaginate.js to implement the Async Select. When a new option is selected it will call a Props function to update the external state in App.js:

import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { AsyncPaginate } from "react-select-async-paginate";

const SelectAsyncPaginate = (props) => {
  const [regionName, setRegionName] = useState(null);

  useEffect(() => {
    setRegionName(props.regionName);
  }, [props.regionName]);

  const loadOptions = async (searchQuery, loadedOptions, { page }) => {

    const response = await fetch(
      `https://www.anapioficeandfire.com/api/houses?region=${regionName}&page=${page}&pageSize=10`
    );
    const responseJSON = await response.json();

    return {
      options: responseJSON,
      hasMore: responseJSON.length >= 1,
      additional: {
        page: searchQuery ? 2 : page + 1,
      },
    };
  };

  const onChange = (option) => {
    if (typeof props.onChange === "function") {
      props.onChange(option);
    }
  };

  return (
    <AsyncPaginate
      key={JSON.stringify(regionName)}
      value={props.value || ""}
      loadOptions={loadOptions}
      getOptionValue={(option) => option.name}
      getOptionLabel={(option) => option.name}
      onChange={onChange}
      isSearchable={false}
      placeholder="Select House"
      additional={{
        page: 1,
      }}
    />
  );
};

SelectAsyncPaginate.propTypes = {
  regionName: PropTypes.string.isRequired,
  value: PropTypes.object,
  onChange: PropTypes.func,
};

export default SelectAsyncPaginate;

Enter fullscreen mode Exit fullscreen mode

Now we need to include the new SelectAsyncPaginate function to the App.js:

 ...
 function App() {
 ...
    <div className="App">
        <Select
          value={region}
          onChange={onchangeSelect}
          options={options}
          getOptionValue={(option) => option.value}
          getOptionLabel={(option) => option.value}
       /> 
       <SelectAsyncPaginate
         regionName={region.value}
         value={currentCountry}
         onChange={(country) => setCurrentCountry(country)}
       />
    </div>
 ...
 }

Enter fullscreen mode Exit fullscreen mode

The result:
react-select-async-paginate

Code available on my GitHub.

References

Top comments (0)