Skip to content
react

Cancelling previous requests in Search bar using Fetch

Mar 6, 2022Abhishek EH4 Min Read
Cancelling previous requests in Search bar using Fetch

In my previous article, I have explained how to cancel previous requests in axios. In this article, we will see how to accomplish the same, while using fetch API

Setting up a mock API

First, let's set up a mock API so that we can query it. Install json-server globally using the following command:

1npm install -g json-server

Create a file named db.json in a place of your choice with the following content:

1{"animals":[{"id":0,"name":"Aardvark"},{"id":1,"name":"Albatross"},{"id":2,"name":"Alligator"},{"id":3,"name":"Alpaca"},{"id":4,"name":"Ant"},{"id":5,"name":"Anteater"},{"id":6,"name":"Antelope"},{"id":7,"name":"Ape"},{"id":8,"name":"Armadillo"},{"id":9,"name":"Donkey"},{"id":10,"name":"Baboon"},{"id":11,"name":"Badger"},{"id":12,"name":"Barracuda"},{"id":13,"name":"Bat"},{"id":14,"name":"Bear"},{"id":15,"name":"Beaver"},{"id":16,"name":"Bee"},{"id":17,"name":"Bison"},{"id":18,"name":"Boar"},{"id":19,"name":"Buffalo"},{"id":20,"name":"Butterfly"},{"id":21,"name":"Camel"},{"id":22,"name":"Capybara"},{"id":23,"name":"Caribou"},{"id":24,"name":"Cassowary"},{"id":25,"name":"Cat"},{"id":26,"name":"Caterpillar"},{"id":27,"name":"Cattle"},{"id":28,"name":"Chamois"},{"id":29,"name":"Cheetah"},{"id":30,"name":"Chicken"},{"id":31,"name":"Chimpanzee"},{"id":32,"name":"Chinchilla"},{"id":33,"name":"Chough"},{"id":34,"name":"Clam"},{"id":35,"name":"Cobra"},{"id":36,"name":"Cockroach"},{"id":37,"name":"Cod"},{"id":38,"name":"Cormorant"},{"id":39,"name":"Coyote"},{"id":40,"name":"Crab"},{"id":41,"name":"Crane"},{"id":42,"name":"Crocodile"},{"id":43,"name":"Crow"},{"id":44,"name":"Curlew"},{"id":45,"name":"Deer"},{"id":46,"name":"Dinosaur"},{"id":47,"name":"Dog"},{"id":48,"name":"Dogfish"},{"id":49,"name":"Dolphin"},{"id":50,"name":"Dotterel"},{"id":51,"name":"Dove"},{"id":52,"name":"Dragonfly"},{"id":53,"name":"Duck"},{"id":54,"name":"Dugong"},{"id":55,"name":"Dunlin"},{"id":56,"name":"Eagle"},{"id":57,"name":"Echidna"},{"id":58,"name":"Eel"},{"id":59,"name":"Eland"},{"id":60,"name":"Elephant"},{"id":61,"name":"Elk"},{"id":62,"name":"Emu"},{"id":63,"name":"Falcon"},{"id":64,"name":"Ferret"},{"id":65,"name":"Finch"},{"id":66,"name":"Fish"},{"id":67,"name":"Flamingo"},{"id":68,"name":"Fly"},{"id":69,"name":"Fox"},{"id":70,"name":"Frog"},{"id":71,"name":"Gaur"},{"id":72,"name":"Gazelle"},{"id":73,"name":"Gerbil"},{"id":74,"name":"Giraffe"},{"id":75,"name":"Gnat"},{"id":76,"name":"Gnu"},{"id":77,"name":"Goat"},{"id":78,"name":"Goldfinch"},{"id":79,"name":"Goldfish"},{"id":80,"name":"Goose"},{"id":81,"name":"Gorilla"},{"id":82,"name":"Goshawk"},{"id":83,"name":"Grasshopper"},{"id":84,"name":"Grouse"},{"id":85,"name":"Guanaco"},{"id":86,"name":"Gull"},{"id":87,"name":"Hamster"},{"id":88,"name":"Hare"},{"id":89,"name":"Hawk"},{"id":90,"name":"Hedgehog"},{"id":91,"name":"Heron"},{"id":92,"name":"Herring"},{"id":93,"name":"Hippopotamus"},{"id":94,"name":"Hornet"},{"id":95,"name":"Horse"},{"id":96,"name":"Human"},{"id":97,"name":"Hummingbird"},{"id":98,"name":"Hyena"},{"id":99,"name":"Ibex"},{"id":100,"name":"Ibis"},{"id":101,"name":"Jackal"},{"id":102,"name":"Jaguar"},{"id":103,"name":"Jay"},{"id":104,"name":"Jellyfish"},{"id":105,"name":"Kangaroo"},{"id":106,"name":"Kingfisher"},{"id":107,"name":"Koala"},{"id":108,"name":"Kookabura"},{"id":109,"name":"Kouprey"},{"id":110,"name":"Kudu"},{"id":111,"name":"Lapwing"},{"id":112,"name":"Lark"},{"id":113,"name":"Lemur"},{"id":114,"name":"Leopard"},{"id":115,"name":"Lion"},{"id":116,"name":"Llama"},{"id":117,"name":"Lobster"},{"id":118,"name":"Locust"},{"id":119,"name":"Loris"},{"id":120,"name":"Louse"},{"id":121,"name":"Lyrebird"},{"id":122,"name":"Magpie"},{"id":123,"name":"Mallard"},{"id":124,"name":"Manatee"},{"id":125,"name":"Mandrill"},{"id":126,"name":"Mantis"},{"id":127,"name":"Marten"},{"id":128,"name":"Meerkat"},{"id":129,"name":"Mink"},{"id":130,"name":"Mole"},{"id":131,"name":"Mongoose"},{"id":132,"name":"Monkey"},{"id":133,"name":"Moose"},{"id":134,"name":"Mosquito"},{"id":135,"name":"Mouse"},{"id":136,"name":"Mule"},{"id":137,"name":"Narwhal"},{"id":138,"name":"Newt"},{"id":139,"name":"Nightingale"},{"id":140,"name":"Octopus"},{"id":141,"name":"Okapi"},{"id":142,"name":"Opossum"},{"id":143,"name":"Oryx"},{"id":144,"name":"Ostrich"},{"id":145,"name":"Otter"},{"id":146,"name":"Owl"},{"id":147,"name":"Oyster"},{"id":148,"name":"Panther"},{"id":149,"name":"Parrot"},{"id":150,"name":"Partridge"},{"id":151,"name":"Peafowl"},{"id":152,"name":"Pelican"},{"id":153,"name":"Penguin"},{"id":154,"name":"Pheasant"},{"id":155,"name":"Pig"},{"id":156,"name":"Pigeon"},{"id":157,"name":"Pony"},{"id":158,"name":"Porcupine"},{"id":159,"name":"Porpoise"},{"id":160,"name":"Quail"},{"id":161,"name":"Quelea"},{"id":162,"name":"Quetzal"},{"id":163,"name":"Rabbit"},{"id":164,"name":"Raccoon"},{"id":165,"name":"Rail"},{"id":166,"name":"Ram"},{"id":167,"name":"Rat"},{"id":168,"name":"Raven"},{"id":169,"name":"Red deer"},{"id":170,"name":"Red panda"},{"id":171,"name":"Reindeer"},{"id":172,"name":"Rhinoceros"},{"id":173,"name":"Rook"},{"id":174,"name":"Salamander"},{"id":175,"name":"Salmon"},{"id":176,"name":"Sand Dollar"},{"id":177,"name":"Sandpiper"},{"id":178,"name":"Sardine"},{"id":179,"name":"Scorpion"},{"id":180,"name":"Seahorse"},{"id":181,"name":"Seal"},{"id":182,"name":"Shark"},{"id":183,"name":"Sheep"},{"id":184,"name":"Shrew"},{"id":185,"name":"Skunk"},{"id":186,"name":"Snail"},{"id":187,"name":"Snake"},{"id":188,"name":"Sparrow"},{"id":189,"name":"Spider"},{"id":190,"name":"Spoonbill"},{"id":191,"name":"Squid"},{"id":192,"name":"Squirrel"},{"id":193,"name":"Starling"},{"id":194,"name":"Stingray"},{"id":195,"name":"Stinkbug"},{"id":196,"name":"Stork"},{"id":197,"name":"Swallow"},{"id":198,"name":"Swan"},{"id":199,"name":"Tapir"},{"id":200,"name":"Tarsier"},{"id":201,"name":"Termite"},{"id":202,"name":"Tiger"},{"id":203,"name":"Toad"},{"id":204,"name":"Trout"},{"id":205,"name":"Turkey"},{"id":206,"name":"Turtle"},{"id":207,"name":"Viper"},{"id":208,"name":"Vulture"},{"id":209,"name":"Wallaby"},{"id":210,"name":"Walrus"},{"id":211,"name":"Wasp"},{"id":212,"name":"Weasel"},{"id":213,"name":"Whale"},{"id":214,"name":"Wildcat"},{"id":215,"name":"Wolf"},{"id":216,"name":"Wolverine"},{"id":217,"name":"Wombat"},{"id":218,"name":"Woodcock"},{"id":219,"name":"Woodpecker"},{"id":220,"name":"Worm"},{"id":221,"name":"Wren"},{"id":222,"name":"Yak"},{"id":223,"name":"Zebra"}]}

Open the directory where db.json is stored in a command prompt and run the following command:

1json-server -p 4000 db.json --delay 3000

Here have created a mock API endpoint at port 4000 with a delay of 3s. You can access it by opening http://localhost:4000/animals

JavaScript Implementation

Let's first see how to implement cancelling in JavaScript.

Create a file named search.html with the following content and open it in the browser

search.html
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="UTF-8" />
5 <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 <title>Search Page</title>
8 </head>
9 <style>
10 body {
11 margin-top: 10px;
12 }
13 .search-wrapper {
14 display: flex;
15 justify-content: center;
16 }
17 </style>
18
19 <script>
20 const search = () => {
21 const inputElement = document.querySelector("#search")
22 const searchValue = inputElement.value?.trim()
23 if (searchValue) {
24 fetch("http://localhost:4000/animals?q=" + searchValue)
25 .then(response => response.json())
26 .then(data => console.log("Results for " + searchValue, data))
27 .catch(err => {
28 console.log(err)
29 })
30 }
31 }
32 </script>
33 <body>
34 <div class="search-wrapper">
35 <input
36 type="text"
37 name="search"
38 id="search"
39 placeholder="Type query..."
40 onkeyup="search()"
41 />
42 </div>
43 </body>
44</html>

In the above code, we have a text box and when the user types something in the text box we call the mock API.

If you open the app in your browser and type cat in the search box, you will see that the API is getting called thrice:

fetch logs

Since the API is slow and user will finish typing cat even before the result for c is received, we can cancel the previous request if the search term is changed.

search.html
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="UTF-8" />
5 <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 <title>Search Page</title>
8 </head>
9 <style>
10 body {
11 margin-top: 10px;
12 }
13 .search-wrapper {
14 display: flex;
15 justify-content: center;
16 }
17 </style>
18
19 <script>
20 const search = () => {
21 const inputElement = document.querySelector("#search")
22 const searchValue = inputElement.value?.trim()
23 if (searchValue) {
24 if (window.controller) {
25 window.controller.abort()
26 }
27 window.controller = new AbortController()
28 window.signal = window.controller.signal
29
30 fetch("http://localhost:4000/animals?q=" + searchValue, {
31 signal: signal,
32 })
33 .then(response => response.json())
34 .then(data => console.log("Results for " + searchValue, data))
35 .catch(err => {
36 console.log(err)
37 })
38 }
39 }
40 </script>
41 <body>
42 <div class="search-wrapper">
43 <input
44 type="text"
45 name="search"
46 id="search"
47 placeholder="Type query..."
48 onkeyup="search()"
49 />
50 </div>
51 </body>
52</html>

In the above code, we are creating an AbortController, which can be used to cancel the web requests and passing the AbortSignal instance received from it to the fetch API.

When the next request arrives, if the controller exists, then we are calling the abort() function to cancel the previous request.

If you search for cat and check the network tab, you will see the previous requests being canceled:

fetch cancel logs

React Implementation

You can achieve the same in React using the following code:

App.js
1import { useState } from "react"
2
3let controller, signal
4function App() {
5 const [searchTerm, setSearchTerm] = useState("")
6
7 const search = e => {
8 const value = e.target.value
9 setSearchTerm(value)
10 if (value?.trim()) {
11 if (controller) {
12 controller.abort()
13 }
14 controller = new AbortController()
15 signal = controller.signal
16
17 fetch("http://localhost:4000/animals?q=" + value, {
18 signal: signal,
19 })
20 .then(response => response.json())
21 .then(data => console.log("Results for " + value, data))
22 .catch(err => {
23 console.log(err)
24 })
25 }
26 }
27 return (
28 <div className="App">
29 <input
30 type="text"
31 name="search"
32 onChange={search}
33 placeholder="Type query..."
34 value={searchTerm}
35 />
36 </div>
37 )
38}
39
40export default App

Source code

You can view the source code of the app here.

Do follow me on twitter where I post developer insights more often!

Leave a Comment

© 2024 CodingDeft.Com