logo icon

OKSANA

KOROBANOVA

magnifying glass on white table
Back to all posts

Building a React Country Search Component with Asynchronous Data Fetching

I will show you how to build a real-world small project.


Date:


Introduction

I came across a small task on Upwork and decided that those types of tasks a Front-end developer would have almost at every project.

small task

In this article, I'll guide you through building a React Country Search component that asynchronously fetches country data from the REST Countries API. The component will include features such as real-time search with the debouncing mechanism.

Setting Up the React App

Assuming you have a React app already set up, you can create a new component for the Country Search. Let's name it CountrySearch.js.

Creating the CountryInput Component

Here's the initial structure of the CountryInput component:

1import { useEffect, useState } from 'react';
2import styles from './Input.module.css';
3import CountriesOptions from './CountriesOptions';
4
5const CountryInput = ({ value, setValue }) => {
6  const [inputValue, setInputValue] = useState(value?.name?.common);
7
8  const [isActive, setIsActive] = useState(false);
9  const [isLoading, setIsLoading] = useState(false); // status of data loading
10  const [options, setOptions] = useState([]); // list of countries by provided name (inputValue)
11
12  const handleInputChange = (e) => {
13    setInputValue(e.target.value);
14  };
15
16  const resetAutocomplete = (val) => {
17    setInputValue(val.name.common);
18    setIsActive(false);
19    setOptions([]);
20  };
21
22  const handleSelectCountry = (value) => {
23    setValue(value);
24    resetAutocomplete(value);
25  };
26
27  useEffect(() => {
28    const getCountries = async () => {
29      setIsLoading(true);
30      try {
31        const response = await fetch(
32          `https://restcountries.com/v3.1/name/${inputValue}`
33        );
34        if (response.ok) {
35          const newOptions = await response.json();
36          setOptions([...newOptions]);
37        }
38      } catch (err) {
39        console.log('Something is incorrect');
40        setOptions([]);
41      } finally {
42        setIsLoading(false);
43      }
44    };
45
46    const debounceTimer = setTimeout(() => {
47      if (inputValue) {
48        getCountries();
49      }
50    }, 500);
51
52    return () => clearTimeout(debounceTimer);
53  }, [inputValue]);
54
55  return (
56    <div className={styles.autoselect}>
57      <input
58        placeholder='Search for a country...'
59        type='text'
60        value={inputValue}
61        onClick={() => setIsActive(true)}
62        onChange={handleInputChange}
63      />
64      {isActive && (
65        <CountriesOptions
66          list={options}
67          onClick={handleSelectCountry}
68          isLoading={isLoading}
69        />
70      )}
71    </div>
72  );
73};
74
75export default CountryInput;

Countries options

1import Loading from './Loading';
2import styles from './CountriesOptions.module.css';
3
4const CountriesOptions = ({ list, onClick, isLoading }) => {
5  return (
6    <div className={styles.popup}>
7      {isLoading && <Loading />}
8      {!list.length && !isLoading && 'No available options'}
9
10      {list.length > 0 && !isLoading && (
11        <ul className={styles.list}>
12          {list.map((country) => (
13            <li
14              key={country.name.common}
15              className={styles.listItem}
16              onClick={() => onClick(country)}>
17              {country.name.common}
18            </li>
19          ))}
20        </ul>
21      )}
22    </div>
23  );
24};
25
26export default CountriesOptions;

Integrating the Component

To use this component in your application, import it where needed and include it in your JSX structure. For example:

1import { useState } from 'react';
2import './App.css';
3import CountryInput from './components/CountryInput';
4
5function App() {
6  const [value, setValue] = useState();
7  return (
8    <div className='App'>
9      <CountryInput value={value} setValue={setValue} />
10      <div>
11        {value ? (
12          <>
13            <h3>{`Some information about ${value.name.common}`}</h3>
14            <p>Capital: {value.capital}</p>
15            <p>Population: {value.population} </p>
16          </>
17        ) : (
18          <h3>Select country to get some information</h3>
19        )}
20      </div>
21    </div>
22  );
23}
24
25export default App;

Conclusion

result img

With this React Country Search component, you've integrated real-time data fetching, debouncing for efficient search calls, and a dropdown for selecting countries. Feel free to customize the styles and enhance the functionality based on your specific project requirements. Building such components not only provides a seamless user experience but also showcases the power and flexibility of React in handling asynchronous operations.