Obsessed with React and teaching. I help people become Frontend Developers. Living with my fiancee and Yorkshire Terrier 🐶 in Poland.
Obsessed with React and teaching. I help people become Frontend Developers. Living with my fiancee and Yorkshire Terrier 🐶 in Poland.

Fetch Data In React As User Types Or Clicks

Jan 31, 2021
10 min read

DESCRIPTION

Let's dive into a bit more complex examples of real-world scenarios. We'll fetch data when the user types in the search field or clicks on the button.

Introduction

In the previous How To Fetch Data In React From API guide, we covered data fetching topics in useEffect hook when the component mounts. I skipped the explanation of fetching data when the component updates (e.g. by typing in) or by clicking on something and triggering the event. I'll implement these 2 approaches and thoroughly explain them for you in this article.

Fetch data as we type

Please, take a look at below example application and refer to it as we'll recreate the exact same version step by step.

Prepare data fetching

We're recreating a similar code as in the previous article with some small but crucial differences. searchQuery will track what user types in our search field (we'll add it soon). useEffect instead of empty dependencies [] has [searchQuery]. It means, it'll run every time searchQuery is updated. When searchQuery is an empty string, we return the initial state of pokemon data which is undefined.
As previously, we're using pokeAPI and when searchQuery is updated, we use browser fetch with async/await to get particular Pokemon data and save it in the state with setPokemon function. Again, please notice response.json() to get an actual JSON from the HTTP response. All of that happens inside of fetchData async. function as useEffect should return either nothing or cleanup function.

Adding search field

For rapid prototyping, we're using Material UI components and its icon package to include a nice search icon on the right of our search field.
An important aspect is about Controlled Components in React as we added handleChange function and attached it to the TextField component. Please, note value={searchQuery} too. With all of it, we'll be able to track what user types and update it appropriately to trigger a new query to pokeAPI.

Adding missing pieces

I've added more Material UI components to render our searched Pokemon in a card (name, image). To prevent unexpected errors (e.g. when pokemon doesn't exist and we won't receive data from the pokeAPI), there is a try...catch clause.
All gucci but wait a moment...

Are we hitting the API with each character typed in? 🙈

Yes, we're currently fetching data from the API on every character being typed in by the user. It'll hit the performance and if you're using APIs with limits (e.g. 100 or 1000 per hour), it'll quickly burn out.
To solve it, we'll use useDebouncedEffect (big thanks to the author of it), debounce technique is useful if you want to execute the function only after some cooling period (in our case, fetch) instead of doing it after every key pressed. Read Debounce vs Throttle to learn more about it.
I won't dive into the details of this hook as you can find an in-depth explanation in the above link. Create a file called useDebouncedEffect.js as we'll import the useDebouncedEffect hook from it in our code below.
We replaced useEffect hook with the useDebouncedEffect. The first argument is still a function but the second one is a number, we provided 300, the last argument is a list of dependencies as in useEffect hook.
The crucial part is about the number as we're not going to fetch the data unless there was 300 milliseconds cooling period (the user didn't type any letter for that time).
Wow, I understand know why there are so few resources available on the Web about this technique. It's quite difficult to explain. 😅 I hope it'll be useful to you at some point. Let's take a look at our finished application one more time for reference. Try to search for your favorite Pokemon, let's bring back the memories. (I think I love Charizard the most ❤️).

Fetch data on click

This part should be much easier 😀, I'll refactor the above code to achieve the end result.
I've used couple of additional Material UI components, including Grid and Button to create the example application.
useDebouncedEffect was completely replaced by handlePokemonFetchClick async. function. We're using almost the same code in it as previously, and it's triggered when the user clicks the button (please, notice onClick={handlePokemonFetchClick} on the Button component). Additionally, we disable the button when there is nothing in the search field. Let's look at our application.

Summary

Perfect, you should be good now in all kinds of data fetching implementations, from standard one to the one when something needs to be typed in, ending with the button click. Good job!
There are more optimizations apart from debouncing we could add including caching or memoizing concepts. react-query handles them well and I'd recommend it instead of custom solutions. However, as you now know the buzzwords, nothing stops you from digging in. I won't promise to make another article about it but who knows... 👀
Big thanks for reading the article, you're awesome! 🙇‍♂️
You can also find me on:
Thanks for all the support. ❤️
logo with a rocket of the BigDevSoon application

Level up your Frontend skills

Code real-world projects based on Figma designs.
spread the word
Did you like this post? Share it with the world! 🌐