How to build a React Live Search (Rick & Morty Edition)

In this short tutorial I show you how to fetch and filter data from an API with React JS.

I also made a step by step video

List of contents

Create React App

To create a new react application open your terminal and run the following command:

npx create-react-app react-live-search

This creates a complete react application. With cd spotify-react && yarn start you jump into the projects directy and start the development server which then runs at http://localhost:3000 by default.

(If for whatever reason the port is not 3000 make sure to change the redirect url in your spotify app settings.)

Clean Up

Before we start to code let's remove the unnecessary stuff we don't need. So remove everythin inside of App.css and in App.js remove the imports as well as the html inside of the div with className App.
So your App.js will look similar to this:

import './App.css';

function App() {

    return (
        <div className="App">

        </div>
    );
}

export default App;

Fetch Data

Now we are ready to implement the function to fetch Data from the Rick & Morty API.

Install axios which will handle our HTTP request with following command

yarn add axios

and import it to the app

import axios from 'axios";

Before we fetch data, we want a state where we can save the data. For that we are going to use the useState Hook. So let's import it and create a new state variable characters:

Add at top of the App.js
import {useState} from 'react';

Inside of App() add:

const [query, setQuery] = useState("")

Since we want to fetch the data immediatly when we open up our app, we need the useEffecthook. So import that as well from react.

Adjust import statement at top of the App.js and add the useEffect hook to App function.

You App.js should now look like this:

import './App.css';
import {useEffect, useState} from 'react';
import axios from 'axios';

function App() {
    const [characters, setCharacters] = useState([])

    useEffect(() => {

    }, [])

    return (
        <div className="App">

        </div>
    );
}

export default App;

Inside of useEffect we now want to declare the fetchData function which performs async get Request to the API Endpoint and gets the wanted data. We wrap our code inside of a try/catch block to handle possible errors.
The fetched data will be stored in the characters state calling the setCharacters function.

const fetchData = async () => {
            try {
                const {data} = await axios.get(`https://rickandmortyapi.com/api/character/`)
                setCharacters(data.results)
            } catch (error) {
                console.error(error)
            }
        }

And then we simply have to call this function:

fetchData()

Display Data

Now we have our data stored in the state, and we are ready to dispaly it in the frontend.

For that create a new div and inside of it we are going to map over the characters Array and dispaly the characters name as well as the image.

<div className="results">
    {characters.map(character => (
        <div key={character.id}>
            <img src={character.image} alt={character.name}/>
                {character.name}
        </div
    ))}
</div>

If you want you can add some styling to your App.css.

.results {
    display: grid;
    gap: 15px;
    grid-template-columns: repeat(4, 1fr);
    max-width: 1200px;
    margin-left: auto;
    margin-right: auto;
    margin-top: 50px;
}

.search {
    background-color: darkgray;
    text-align: center;
    padding: 15px;
}

.input {
    font-size: 25px;
}

When you now visit your browser at http://localhost:3000 you should be able to see the data we just fetched. Now we are ready for the last step.

Filter Search Results

Add search input

In order to filter the search results, we need to create a new state called query and set it to an empty string initially.

const [query, setQuery] = useState("")

As well as we need an input field which updates the states as soon as we start typing. For that lets create this input field and add an onChange event which triggers the state update. The value of the input field needs to contain the query states value:

<div className="search">
    <input  type="text"
            placeholder={"Search Character"}
            className={"input"}
            onChange={event => setQuery(event.target.value)}
            value={query}
    />
</div>

Update search results

Now we need to update our search result. To achive that we need to adjust our fetching endpoint. We need to add a "name" paramater and pass our search query into that.

Adjust this line of code:

const {data} = await axios.get(`https://rickandmortyapi.com/api/character/?name=${query}`)

Let me explain that: Initially the query variable is set to an empty string what means that we are not passing a param of name. That means we perform the regular call and get 20 first characters.

The problem now is, since we pass an empty dependancy array to the useEffect hook the fetchData function will not be called again if we start typing our search query. To fix that we need to add query as an dependancy to the useEffect hook. So your useEffect will now look like this:

useEffect(() => {
    const fetchData = async () => {
        try {
            const {data} = await axios.get(`https://rickandmortyapi.com/api/character/?name=${query}`)
            setCharacters(data.results)
        } catch (error) {
            console.error(error)
        }
    }

    fetchData()
}, [query])

With this changes the useEffect and also the fetchData will be called and we get new search results depending on our query state.

Visit you application at http://localhost:3000 and start typing inside your input field. The results now should update immediatly.

That's it! Thanks for reading! I would love to see a comment with any kind of feedback!

Step by Step Video

21