Making delayed network requests in React after state changes
Tags: react, javascript
Published: 2021-09-14 05:23:31

> Originally posted in my [blog](https://akhilaariyachandra.com/blog/making-delayed-network-requests-in-react-with-settimeout-and-useeffect) on 13th September 2021

Cover by [Erik Mclean](https://unsplash.com/@introspectivedsgn?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

Recently I switched the database used in my site for page views and reactions from PostgreSQL to [PlanetScale](https://planetscale.com/).

With the change I also thought it would be a good chance to redesign the reactions section of the posts.

![Reactions Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cup93ii4qmrnax6linqx.gif)

Implementing the button and animation with [react-spring](https://react-spring.io/) was relatively easy, but I had a choice of how I wanted to make the network request to save the result.

I could either save the result everytime a visitor clicks the button incrementing the value in the database by one, or wait for a certain time after the visitor finishes clicking and save that result.

Saving on every click would be the easiest but it would create problems such as race conditions, issues with the optimistic UI updates I'm handling with [React Query](https://react-query.tanstack.com/) and rate limits with any hosting provider. So my best option was the second one.

## How I implemented it

In my case I started with a state to store the reaction count.

```tsx
const [reactionCount, setReactionCount] = useState<number>(0);
```

I also had a value called `count` which is the acual reaction count in the database.

```tsx
const { count, react } = useReaction(id);
```

`react` is the function that is used to make the network request to update the value in the database.

The first thing I had to do was to create a side effect to make the network request after the state changes.

```tsx
useEffect(() => {}, [reactionCount, count]);
```

Next I used `setTimeout` to call `react` one second after `reactionChanges`. I also added an extra check to make sure `react` is not called if there is no difference between `reactionCount` and `count`.

```tsx
useEffect(() => {
  const timeout = setTimeout(() => {
    if (reactionCount !== count) {
      react(reactionCount - count);
    }
  }, 1000);
}, [reactionCount, count]);
```

Finally I had to handle the case where the visitor clicks the button multiple times all less than a second apart each other. In this case I had to use the `useEffect` cleanup function to remove the previous `timeout` in order for a new `timeout`.

```tsx
useEffect(() => {
  const timeout = setTimeout(() => {
    if (reactionCount !== count) {
      react(reactionCount - count);
    }
  }, 1000);

  return () => clearTimeout(timeout);
}, [reactionCount, count]);
```

So now when `reactionCount` changes, the `timeout` set for that particular value of `reactionCount` is cleared and a new `timeout` is set.

![Network tab example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/te0vaa8maq6z7eo97u4k.gif)

You can see the code in action in [my original post](https://akhilaariyachandra.com/blog/making-delayed-network-requests-in-react-with-settimeout-and-useeffect). 😊