Improving Search Bar Responsiveness with React Effects

Improving Search Bar Responsiveness with React Effects

Let's Explore React Effects and How We Can Use Them for Optimal UI Performance

Effects allow you to specify side effects that are caused by rendering itself, rather than by a particular event.

The basic syntax of an Effect looks like this:

useEffect(() => {
  // your code...
}, []);

In the empty square brackets, you can add dependencies on which you want to trigger that effect. Keep it empty if you want the effect to trigger on component mount.

The behaviors without the dependency array and with an empty [] dependency array are different:

useEffect(() => {
  // This runs after every render
});

useEffect(() => {
  // This runs only on mount (when the component appears)
}, []);

useEffect(() => {
  // This runs on mount and also if productSearch have changed since the last render
}, [productSearch]);

You may have noticed a lag in search bar suggestions on e-commerce or social sites. The main reason behind that is using Effects without cleanup! – yes, you heard it right.

Let's dive into it today!

Some Effects need to specify how to stop, undo, or clean up whatever they were doing. For example, 'connect' needs 'disconnect,' 'subscribe' needs 'unsubscribe,' and 'fetch' needs either 'cancel' or 'ignore'. We use cleanup in such cases.

Let's take an example of a Search Bar Suggestion without cleanup: when we enter text for a search, it fetches suggestions for the given input.

If we try to enter text quickly, like typing 'a' first followed by 'b,' then our search bar may have 'ab' as the search text, but our suggestion box will show suggestions for 'a' and then 'ab' (or vice versa), depending on which API call completes first.

This behavior is not what users expect, and we need a way to stop calling previous API calls (suggestions for 'a') when the priority is the latest API call (suggestions for 'ab').

We can achieve this by adding a cleanup mechanism in the Effect. React will call your cleanup function each time before the Effect runs again, and one final time when the component unmounts (gets removed).

React always cleans up the previous render's Effect before the next render's Effect.

useEffect(() => {
    //cleanup block of effect
    return () => {
        //cleanup code
    }
},[dependencies])

This is how our Suggestion component looks:

import { useState, useEffect } from 'react';

function SearchBar() {
  const [text, setText] = useState('');
  const [suggestions, setSuggestions] = useState([]);

  useEffect(() => {
    let shouldFetch = true;
    // fetchSuggestions is the function to fetch suggestions using external API
    fetchSuggestions(text).then(suggestions => {
      if(shouldFetch) {
        setSuggestions(suggestions);
      }
    });
    return () => {
      shouldFetch = false;
    };
  }, [text]);

  return (
    <>
      <label>
        What to Search:{' '}
        <input
          value={text}
          onChange={e => setText(e.target.value)}
        />
      </label>
      <ul>
      {suggestions.map(suggestion => (
         <li>{suggestion}</li>   
      )}
      </ul>
    </>
  );
}

Let's see what exactly happens as the user changes the text in the search bar.

You can't "undo" a network request that has already happened, but your cleanup function should ensure that the fetch that's no longer relevant doesn't keep affecting your application.

Initially, the user has added a in the text box, which triggers our Effect for text = 'a' and starts fetching suggestions for that. Within a second, the user has added b after a, so our search text becomes ab. This unmounts the state with text = 'a', which triggers the cleanup function. In this function, we set shouldFetch = false, so even if the API returns suggestions for text a, we don't save them to our suggestion state because our state has changed to the new text ab. As our new text is ab, it will start fetching suggestions for text = 'ab', and since this is the present state that's mounted, cleanup will not trigger. So our shouldFetch flag is true, and it will successfully save the suggestions for the latest inputted text.

This is how we can improve the user experience of the search bar's responsiveness using Effects with Cleanup.

You can try commenting out the cleanup block to see how it works without cleanup.

User experience is essential, as our brand value depends on it.

So, let's let our brand grow with the power of React ⚛️!!