Create react form without making multiple requests
Tags: react, axios
Published: 2021-07-22 06:43:37

If you're reading this, maybe you've been in a situation where you're making a react form where you hit an API when you type in the search box, but the downside is when you type 'batman', the axios made 6 different requests which is 'b', 'ba', 'bat', 'batm', 'batma', and the actual query we're looking for, 'batman'. I hope this article works for you. Let's get started!



Assuming you've initialized the react app by using:

```bash
npx create-react-app .
```

and installed axios by using:

```bash
npm i axios
```



Let's start with initial code in `app.js`, we'll make a book search feature:

```jsx
import './App.css';

function App() {
  return (
    <div className="App">
    	<input type="text" />
     	<div>Result</div>
      <div>Loading...</div>
      <div>Error</div>
    </div>
  );
}
```

Inside the default `App` div, we put a `text input` and three different `div`s, each for result, loading, and error.

Now we create our states by importing `useState` and `useEffect`:

```jsx
import { useState, useEffect } from 'react'
```

and define our book states at the beginning of the App function (before return):

```jsx
const [query, setQuery] = useState('')
const [loading, setLoading] = useState(true)
const [error, setError] = useState(true)
const [books, setBooks] = useState([])
```

Then we'll create the axios request in the `useEffect` hook:

```jsx
useEffect(() => {
  setLoading(true)
  axios({
    method: 'get',
    url: 'http://openlibrary.org/search.json',
    params: { q: query }
  })
  	.then(response => {
    	let data = response.data.docs.map(book => book.title)
      console.log({ query, data })
    	setBooks(data)
    	setLoading(false)
  	})
  	.catch(err => {
    	setError(err)
    	setLoading(false)
  	})
}, [query])
```

We set the `loading` value with `true` to indicate that the axios is sending a request to the url, and set it to false after we get either result. And we set the `books` value with only their title if it succeeded, and set the `error` if it failed.

Then we 'rework' the three `div`s like this:

```jsx
{
  books.map((book, index) => {
    return <div key={book}>{ book }</div>
  })
}
{
  loading &&
  <div>Loading..</div>
}
{
  error &&
  <div>Error</div>
}
```

And after you run it by using:

```bash
npm run start
```

and type 'batman', it should look like this:
![Chrome console showing 6 requests](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xb4uewmuhoccs6k83wj3.png)

Notice the queries were finished in an order we don't want, so the most recent query we'll get is the query 'b' instead of 'batman'. So now we'll make it so the axios only take the last change made in the input, which is 'batman'.

## axios.CancelToken

Actually axios has an option called `cancelToken` that can be used to cancel the request. How do we do that? By putting it to the option when we make a request:

```jsx
useEffect(() => {
  let cancel;
  console.log('axios called')
  axios({
    method: 'get',
    url: 'http://openlibrary.org/search.json',
    params: { q: query },
    cancelToken: new axios.CancelToken(c => cancel = c)
  })
    .then(...)
    .catch(...)
  return () => cancel()
})
```

The `cancel` variable will then hold the cancel function from  `axios.CancelToken`, and will be called in useEffect callback return so axios will be cancelled once another useEffect is triggered.

Now we can test it out by running:

```bash
npm run start
```

And type 'batman' in our search box, we'll only get one request
![Chrome console showing one request](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tg8froxjw1k2bq0v3kbv.png)

Notice that axios was called 6 times, but only 'batman' request was sent, because the 'b', 'ba', 'bat', 'batm', 'batma' requests are cancelled.

Lastly, we'll get an error for every request cancellation, but because that is intended we can filter the error out by adding conditional in our catch block:

```jsx
.catch(err => {
  if (axios.isCancel(err)) return
  ...
})
```

source:
Web Dev Simplified
https://www.youtube.com/watch?v=NZKUirTtxcg

Axios Documentation
https://github.com/axios/axios