John Au-Yeung I'm a web developer interested in JavaScript stuff.

5 top React Hooks libraries compared

8 min read 2457

5 Top React Hooks Libraries Compared

React’s Hooks API is now the de facto method for creating components. It coexists alongside the class component API, which lets us create components with JavaScript classes.

In addition to the standard Hooks that come with the React library, developers can create their own Hooks. Unsurprisingly, many custom Hooks libraries have since popped up to make creating React apps even easier.

In this article, we’ll look at five useful React Hooks libraries and compare their utility

1. React Hooks Lib

React Hooks Lib provides us with Hooks that resemble the lifecycle methods of React class components.

For example, it offers Hooks like useDidMount, which runs when the component is mounted, and useDidUpdate, which runs when the component updates. It also has Hooks for managing states, like useCounter, which add a number state with its own functions to manage it.

To install the package, we can run:

npm i react-hooks-lib --save

Then we can use some of the Hooks by importing them from the module. We can use the useDidMount Hook by writing:

import React from "react";
import { useDidMount } from "react-hooks-lib";

export default function App() {
  useDidMount(() => {
    console.log("did mount");
  });

  return (
    <div className="App">
      <h1>Hello world</h1>
    </div>
  );
}

Likewise, we can use the useCounter Hook by writing:

import React from "react";
import { useCounter } from "react-hooks-lib";

export default function App() {
  const { count, inc, dec, reset } = useCounter(0);
  return (
    <div>
      {count}
      <button onClick={() => inc(1)}>increment</button>
      <button onClick={() => dec(1)}>decrement</button>
      <button onClick={reset}>reset</button>
    </div>
  );
}

It returns an object with the count state and the inc, dec, and reset methods. Let’s break down what these methods do:

  • inc increments count by a given number
  • dec decrements count by a given number
  • reset resets the count to the initial value

React Hooks Lib also comes with the useField Hook to make getting and setting input values easier. We can use it by writing:

We made a custom demo for .
No really. Click here to check it out.

import React from "react";
import { useField } from "react-hooks-lib";

export default function App() {
  const { value, bind } = useField("text");

  return (
    <div>
      <input type="text" {...bind} />
      <p>{value}</p>
    </div>
  );
}

We just pass the whole bind object into the input, and we can use it to get the data from the input and set it as the value of value. bind also has the value property to set the input value.

It also works with select elements:

import React from "react";
import { useField } from "react-hooks-lib";

export default function App() {
  const { value, bind } = useField("text");

  return (
    <div>
      <select {...bind}>
        <option value="apple">apple</option>
        <option value="orange">orange</option>
      </select>
      <p>{value}</p>
    </div>
  );
}

React Hooks Lib comes with many other Hooks that provides similar functionality. Overall, it provides us with custom Hooks that can do a few convenient things. We should note, however, that not all the provided Hooks are documented.

2. react-hanger

react-hanger is a library that provides us with React Hooks to let us more easily manage various kinds of states. It comes with the following Hooks:

  • useInput – get and set input control values
  • useBoolean – get and set Boolean states
  • useNumber – get and set number states
  • useArray – get and set array states
  • useOnMount – run code when a component mounts
  • useOnUnmount – run code when a component unmounts
  • useStateful – get and set component state

We can use useInput to as follows to make processing input values simpler:

import React from "react";
import { useInput } from "react-hanger";

export default function App() {
  const input = useInput("");

  return (
    <div>
      <input type="text" value={input.value} onChange={input.onChange} />
      <p>{input.value}</p>
    </div>
  );
}

We can use the useNumber to get and set a number state:

import React from "react";
import { useNumber } from "react-hanger";

export default function App() {
  const counter = useNumber(3, { lowerLimit: 0, upperLimit: 5 });

  return (
    <div>
      <p> {counter.value} </p>
      <button onClick={() => counter.increase()}> increase </button>
      <button onClick={() => counter.decrease()}> decrease </button>
    </div>
  );
}

We can set counter.value‘s initial value with the first argument, and we can set the lower and upper limit of the counter.value state with the second. The useArray and useBoolean Hooks work in a similar way.

To set any kind of state, we can use the useStateful Hook:

import React from "react";
import { useStateful } from "react-hanger";

export default function App() {
  const username = useStateful("tom");

  return (
    <div>
      <p> {username.value} </p>
      <button onClick={() => username.setValue("tom")}> tom </button>
      <button onClick={() => username.setValue("jerry")}> jerry </button>
    </div>
  );
}

It’s better than React’s useState Hook in that we can get the value of the state from the value property, and we can set the value with the setValue method of the returned object. No destructuring is required to get the state and setter function, unlike React’s inbuilt useState Hook.

3. React hookedUp

Like countless other libraries, React hookedUp lets us manage component states. But we can also use it to manage focus and hovering of HTML elements.

It comes with Hooks that replicate the functionality of class component lifecycle Hooks, as well as a few useful timer and network Hooks that aren’t provided by the other libraries we’ve reviewed so far.

Let’s take a look at the useHover Hook, which will detect if we hover over an input:

import React from "react";
import { useHover } from "react-hookedup";

export default function App() {
  const { hovered, bind } = useHover();

  return (
    <div>
      <p>{hovered ? "hovered" : "not hovered"}</p>
      <input {...bind} />
    </div>
  );
}

We just spread the whole bind object as props for the input. The useFocus Hook can be used in a similar way.

If we miss our good ol’ componentDidMount method in class components, we can use the useOnMount Hook to provide equivalent functionality in function components:

import React from "react";
import { useOnMount } from "react-hookedup";

export default function App() {
  useOnMount(() => console.log("mounted"));
  return <div> hello world </div>;
}

And if we want to call setInterval in our code, we can use the useInterval Hook. For example, we can write:

import React, { useState } from "react";
import { useInterval } from "react-hookedup";

export default function App() {
  const [time, setTime] = useState(new Date().toString());

  useInterval(() => setTime(new Date().toString()), 1000);

  return <p>{time}</p>;
}

We just pass in the callback to run as the first argument and the interval as the second argument, like the setInterval function.

It also comes with the useTimeout Hook to run a callback after a given delay:

import React from "react";
import { useTimeout } from "react-hookedup";

export default function App() {
  useTimeout(() => alert("hello world"), 1500);

  return <h1>hello world</h1>;
}

Another useful Hook from React hookedUp is useOnlineStatus, which allows us to watch the online status of our app. For example, we can write:

import React from "react";
import { useOnlineStatus } from "react-hookedup";

export default function App() {
  const { online } = useOnlineStatus();

  return <h1>{online ? "online" : "offline"}</h1>;
}

It returns the online property, which is true when the device is online.

Like we mentioned earlier, React hookedUp also comes with the suite of state management Hooks that comes with the libraries we looked at earlier. These work similarly to how they work in the other libraries.

4. react-use

The react-use Hooks library comes with a larger collection of Hooks than the other libraries listed so far, including Hooks to leverage the various hardware that browsers can access. It also comes with Hooks to watch screen size, motion, scrolling, animation, and to dynamically adjust CSS, among many others.

For instance, we can use the useMouse Hook to watch the position of a user’s mouse:

import React from "react";
import { useMouse } from "react-use";

export default function App() {
  const ref = React.useRef(null);
  const { docX, docY, posX, posY, elX, elY, elW, elH } = useMouse(ref);

  return (
    <div ref={ref}>
      <div>
        Mouse position in document - ({docX}, {docY})
      </div>
      <div>
        Mouse position in element - ({elX}, {elY})
      </div>
      <div>
        Element position- ({posX} , {posY})
      </div>
      <div>
        Element dimensions - {elW}x{elH}
      </div>
    </div>
  );
}

We can use the docX and docY to get the x- and y-coordinates of the mouse in the document. Also, we can use the elX and elY properties to get the x- and y-coordinates of the mouse in the element being monitored. We assign the ref to the element we want to watch.

Similarly, we can use the useScroll Hook to track the scroll position of an element:

import React from "react";
import { useScroll } from "react-use";

export default function App() {
  const scrollRef = React.useRef(null);
  const { x, y } = useScroll(scrollRef);

  return (
    <div ref={scrollRef} style={{ height: 300, overflowY: "scroll" }}>
      <div style={{ position: "fixed" }}>
        <div>x: {x}</div>
        <div>y: {y}</div>
      </div>
      {Array(100)
        .fill()
        .map((_, i) => (
          <p key={i}>{i}</p>
        ))}
    </div>
  );
}

We assign a ref to the element whose scroll position we want to watch, and we set the height and overflowY to scroll so that we can scroll the content. We get the scroll position with the x and y properties returned.

We can also use Hooks react-use provides for animation. For example, we can use the useSpring Hook to animate number displays:

import React, { useState } from "react";
import useSpring from "react-use/lib/useSpring";

export default function App() {
  const [target, setTarget] = useState(50);
  const value = useSpring(target);

  return (
    <div>
      {value}
      <br />
      <button onClick={() => setTarget(0)}>Set 0</button>
      <button onClick={() => setTarget(200)}>Set 100</button>
    </div>
  );
}

We pass the number to animate to into the useSpring Hook. Then the number will animate until the target is reached. Note that the rebound is required for this Hook to work.

The library also has Hooks to let us commit various side effects, like copying data to the clipboard and manipulating local storage. To add a copy-to-clipboard feature, we can use the useCopyToClipboard Hook:

import React, { useState } from "react";
import useCopyToClipboard from "react-use/lib/useCopyToClipboard";

export default function App() {
  const [text, setText] = useState("");
  const [state, copyToClipboard] = useCopyToClipboard();

  return (
    <div>
      <input value={text} onChange={(e) => setText(e.target.value)} />
      <button type="button" onClick={() => copyToClipboard(text)}>
        copy text
      </button>
      {state.error ? (
        <p>error: {state.error.message}</p>
      ) : (
        state.value && <p>Copied {state.value}</p>
      )}
    </div>
  );
}

We just call useCopyToClipboard in our component to get the copyToClipboard function, then we can call that to copy whatever is passed in as the argument to the clipboard.

Likewise, we can easily work with local storage via the useLocalStorage Hook:

import React from "react";
import useLocalStorage from "react-use/lib/useLocalStorage";

export default function App() {
  const [value, setValue, remove] = useLocalStorage("key", "foo");

  return (
    <div>
      <div>Value: {value}</div>
      <button onClick={() => setValue("bar")}>bar</button>
      <button onClick={() => setValue("baz")}>baz</button>
      <button onClick={() => remove()}>Remove</button>
    </div>
  );
}

value has the value of the local storage entry with the given key, setValue lets us pass in the value to set, and remove removes the entry from local storage.

In addition to the aforementioned Hooks, which are unique to react-use, the library comes with many Hooks for setting states, using browser APIs, running async code, and much more. react-use is by far the most comprehensive Hooks library we’ve looked at so far.

5. React Recipes

React Recipes is another Hooks library that comes with many custom Hooks. It offers many of the same Hooks as react-use, such as Hooks that use browser APIs, manage states, run async code, etc.

For example, we can use the useSpeechSynthesis Hook to make the browser speak:

import React, { useState } from "react";
import { useSpeechSynthesis } from "react-recipes";

export default function App() {
  const [value, setValue] = useState("");
  const [ended, setEnded] = useState(false);
  const onBoundary = (event) => {
    console.log(`${event.name}: ${event.elapsedTime} milliseconds.`);
  };
  const onEnd = () => setEnded(true);
  const onError = (event) => {
    console.warn(event);
  };

  const {
    cancel,
    speak,
    speaking,
    supported,
    voices,
    pause,
    resume
  } = useSpeechSynthesis({
    onEnd,
    onBoundary,
    onError
  });

  if (!supported) {
    return "Speech is not supported.";
  }

  return (
    <div>
      <input value={value} onChange={(event) => setValue(event.target.value)} />
      <button
        type="button"
        onClick={() => speak({ text: value, voice: voices[1] })}
      >
        Speak
      </button>
      <button type="button" onClick={cancel}>
        Cancel
      </button>
      <button type="button" onClick={pause}>
        Pause
      </button>
      <button type="button" onClick={resume}>
        Resume
      </button>
      <p>{speaking && "Voice is speaking"}</p>
      <p>{ended && "Voice has ended"}</p>
      <div>
        <h2>Voices:</h2>
        <div>
          {voices.map((voice) => (
            <p key={voice.name}>{voice.name}</p>
          ))}
        </div>
      </div>
    </div>
  );
}

We call the useSpeechSynthesis Hook, which returns an object with various properties:

  • cancel cancels the speech synthesis
  • speak makes the browser start speaking
  • speaking is a Boolean that tells us whether speech synthesis is in process
  • supported is a Boolean that informs us whether speech synthesis is supported in the current browser
  • voices has the list of voices to choose from
  • pause lets us pause speaking
  • resume lets us resume speaking

It comes with many Hooks listed here, which provide us with lots of functionality that isn’t provided by React itself out of the box. It’s also worth nothing that it is a truly well-documented and comprehensive library.

The verdict?

By far the most comprehensive and useful React Hooks libraries we reviewed today are react-use and React Recipes. They provide us with lots of Hooks for a variety of use cases so that we don’t have to write them ourselves from scratch.

React Hooks Lib, react-hanger, and React hookedUp provide some basic Hooks for state management that can help us simplify state management to a certain extent. If that’s all we’re looking for out of a Hooks library, then React Hooks Lib, react-hanger, and React hookedUp are useful. They are all easy to use, and all of them (except React Hooks Lib) are clearly documented.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

John Au-Yeung I'm a web developer interested in JavaScript stuff.

Leave a Reply