Wrap your library in a React hook
Tags: react, hook, javascript, typescript
Published: 2022-06-29 09:36:23

---
tags: react, hook, javascript, typescript
series: A JS library for every framework taste
---  

This is the third and last article in a series on designing a Javascript library for different frameworks to use. In the first article in the series, we have built a vanilla TS/JS library for swipe detection in the browser. Although it can be used in your application built with any popular JS framework as is, we want to go a little further and make our library a first-class citizen when used in the framework of your choice.

In this article, we are going to wrap our swipe detection library in a React hook.

:bulb: The article implies you are familiar with the public interface of the swipe detection library used under the hood. If you haven't read the first article in the series, [this section](https://dev.to/this-is-learning/detect-swipes-with-reactive-programming-1bph#defining-the-public-interface-of-the-library) alone will be enough to follow along with the material of this one.


### How should it work

We want to wrap the swipe detection functionality of the underlying library in a reusable React hook. Let's call one `useSwipe` as it is important to follow the hooks naming convention. This is how the hook will be used in a consumer component:

```tsx
const swipeElement = useSwipe({
  onSwipeEnd: (event: SwipeEvent) => {
    console.log(`SwipeEnd direction: ${event.direction} and distance: ${event.distance}`);
  }
});

return <div ref={swipeElement}>Swipe me!</div>
```

### Complete solution
The wrapper hook will be quite concise:

```typescript
import { createSwipeSubscription, SwipeSubscriptionConfig } from 'ag-swipe-core';
import { RefCallback, useCallback } from 'react';
import { Subscription } from 'rxjs';

export const useSwipe = (config: Pick<SwipeSubscriptionConfig, 'onSwipeMove' | 'onSwipeEnd'>): RefCallback<HTMLElement> => {
  let swipeSubscription: Subscription | undefined;

  return useCallback((domElement: HTMLElement) => {
    if (domElement) {
      swipeSubscription = createSwipeSubscription({
        domElement,
        ...config
      });
    } else {
      swipeSubscription?.unsubscribe?.();
    }
  }, []);
}
```

What we want from the hook is:

- get a reference to the DOM element the swipe listener should be attached.
- react to one being mounted/unmounted to perform subscription and unsubscription tasks correspondingly.

Our first intention could be to use a combination of `useRef` and `useEffect` hooks, but what we actually need is a combination of `ref` and `useCallback`:

> ... the callback ref will be called only when the component mounts and unmounts

Couldn't ask for a better fit. If the `domElement` parameter value coming from `ref` is truthy i.e. component has been mounted, we call `createSwipeSubscription` with provided `onSwipeMove` and/or `onSwipeEnd` handlers. If the value is falsy i.e. the component has been unmounted, we use the `swipeSubscription` reference to unsubscribe. 
 
To learn more on how `ref` and `useCallback` work together see [this section in React documentation](https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node). 

### Wrapping up

You can find the complete library code on GitHub by [this link](https://github.com/aGoncharuks/ag-swipe/blob/master/libs/swipe-angular/src/lib/swipe.directive.ts).

And the `npm` package by [this link](https://www.npmjs.com/package/ng-swipe).

That was it! We have built a simple React hook wrapper for our swipe detection library in 17 lines of code. 

This article completes our short series. Thanks for reading and stay tuned!