Wojciech Trawiński
Aug 4 · 6 min read

This blog post is highly inspired by my recent job experience, since I used to work as an Angular developer for long time and due to a little misunderstanding during a recruitment process I ended up as a React developer which was a little pain for an Angular passionate 😢. Fortunately, only for one month and now I’m back in the Angular game 🎲. One of my tasks was to implement a typeahead/live search component, since we could not use any third-party solutions at all and I had to reinvent the wheel 😄. Since a live search example has always been one of my favourite benchmarks when it comes to Angular/RxJS, I would like to compare the implementation of the task in both Angular and React.

Please note that I will focus on typical solutions for each environment. Of course, one may argue that it’s perfectly fine to use the RxJS library in a React application, but that’s not the goal of the article. It aims at comparison of well-known approaches. So without a further ado, let’s dive into the code! 🏊


Introduction

Just to make sure that we’re on the same page, I will briefly list the basic requirements for a live serach component:

  • a user can type a query into an input element,
  • a corresponding list of items matching the query is rendered below the input,
  • an http request is made only for a so-called stable query (the required time has to elapse since a user stopped typing),
  • an http request should not be performed if a stable query has not changed,
  • a race condition has to be handled so that stale results are not rendered.

In my examples I will make use of the JSONPlaceholder REST API which exposes an endpoint for fetching blog posts matching a user id.


Doing it Angular way 🔥

Let’s focus on basic aspects of a solution in Angular. If you’re interested in an in-depth explanation of the RxJS part, I wrote an article about the live search example implemented with the aid of the library which can be found here ⬅️.

Implementing a service

Usually you implement a service which is responsible for performing http requests for a certain domain of your Angular application. That being said, the service which enables fetching user’s posts may look like this:

with the following blog post interface:

For the sake of simplicity, I simply return an empty array for an invalid user id, which is handled by the catchError operator, since the backend service returns a 404 response in such a case.

Implementing a component

Now, you need to implement a component which allows picking a user and renders a list of her/his blog posts. Again, for the sake of simplicity, I have a native input element and a raw list in my example’s template:

Since I do not want to distract your attention from the main topic of the article, I will stick to the simplest solution, namely I will implement a live search logic within the component. However, I highly encourage you to take a look at my previous blog post ⬅️ concerning reusable logic in Angular applications, since you may wish to extract the logic into a dedicated service.

Hence, the component’s class looks like this:

If you are familiar with basic live search/typeahead examples requirements, there is no rocket science in the above code snippet:

  • debounceTime — provide only ‘stable’ values,
  • distinctUntilChanged — skip the same successive values,
  • switchMap — handle race conditions.

Extracting the logic into a custom operator

The logic I have in the component is likely to be reused somewhere else in an Angular application, therefore it’s worth to extract it into a custom RxJS operator. Just to remind you, an operator is simply a function which takes an input stream as its argument and returns an output observable.

Let’s refactor the example using a custom liveSearch operator:

Now, the component class looks cleaner and the live search logic can be easily reused:


Doing it React way 🌈

It’s been around two years since I developed my last real-world application in React and I must admit that things have changed in the React world. First of all, functional components are no longer stateless and with the advent of hooks you should favour functional components over class-based ones. Secondly, TypeScript is supported for React applications out of the box which is a great news. Last but not least, React hooks were introduced which are extremely powerful, however it takes a while to get used to the new way of developing React applications. Summing up, after a short talk with my JavaScript/React mentor Bartosz Cytrowski who simply said that React hooks are awesome, my solution makes use of a statically typed functional component with custom hooks composed of built-in ones.

useDebounce hook

The first hook allows to trigger re-render (and as a result executes other hooks present in a component) when a given value is ‘stable’, namely a required time has elapsed since the last change:

In the above example, everytime the useDebounce hook is called, the built-in useEffect hook is executed. As a result, if any of the arguments (value or delay) change, the teardown logic is performed (clearing the current setTimeout timer) and the setTimeout function is called with a new callback scheduling the debouncedValue update.

useLiveSearch hook

Next step is to define a logic responsible for making an http request for a debounced query only if the current value is different from the previous one:

The useLiveSearch hook makes use of the useDebounce hook in order to receive a ‘stable’ query. If a new debounced value is returned from the hook, the built-in useEffect hook is called. It’s only called when the debouncedQuery changes, since it’s listed in a dependencies array of that hook. Note that it satisfies one of the live search example requirements, namely do not make an http request if a query has not changed. Last but not least, a race condition is handled with the aid of a little trick, namely a response is set only if the isActive flag equals to true. The teardown logic for the useEffect hook toggles the flag which does the job.

This is required for the Promise-based approach, since a Promise object is not cancelable. If you stick to the good old XMLHttpRequest object, you can abort the current request in the body of the teardown logic callback:

You can also use the Axios library which supports a request cancellation.

Request factory

Since in React there is no official notion of a service, you can stick to a simple factory function which returns an http request:

Implementing a component


Conclusions

Since I’m a big enthusiast of the RxJS library, I’m in favour of the solution typical for Angular applications. The requirements are met with the aid of built-in operators which both save a developer’s time and ensure a high quality of your solution thanks to unit tests. On the other hand, React hooks bring a great value, hence it’s much easier to share logic between components and the new approach is more straightforward than using higher-order components. This blog posts is not meant to be a battle between Angular and React so I will not state who’s the winner, I will simply say that for the last two years I became more mature and so did React 😃.

Below you can find links to the examples:


I hope you liked the post and learned something new 👍 If so, please give me some applause 👏

JavaScript everyday

Improve your JavaScript skills everyday!

Wojciech Trawiński

Written by

Doing awesome things using JavaScript

JavaScript everyday

Improve your JavaScript skills everyday!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade