DEV Community

Yaser Adel Mehraban
Yaser Adel Mehraban

Posted on • Originally published at yashints.dev

React hooks you should know about πŸ”₯πŸ”₯πŸ”₯

React Hooks are somewhat a new addition to React. They allow you to use React features without the need to use a class. But I am not going to go through an introduction in this post, there are many great intro posts out there. This post shows you a few nifty hooks and what you can achieve with them.

react-use-form-state hook

Forms are a very common pattern when it comes to getting information from users. From small to large forms, they all have their own state we have to manage, whether it's for validation or to populate another input based on previous selection.

This hook is a handy tool which allows you simplify managing form's state using the native HTML input fields.

You can install it with:

npm i react-use-form-state
Enter fullscreen mode Exit fullscreen mode

And a simple usage:

import { useFormState } from 'react-use-form-state';

export default function SignUpForm({ onSubmit }) {
  const [formState, { text, email, password, radio }] = useFormState();

  function handleSubmit(e) {
    // ...
  }

  return (
    <form onSubmit={handleSubmit}>
      <input {...text('name')} />
      <input {...email('email')} required />
      <input {...password('password')} required minLength="8" />
      <input {...radio('plan', 'free')} />
      <input {...radio('plan', 'premium')} />
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

With this you get a json structure like this:

{
  values: {
    name: 'Mary Poppins',
    email: 'mary@example.com',
    password: '1234',
    plan: 'free',
  },
  touched: {
    name: true,
    email: true,
    password: true,
    plan: true,
  },
  validity: {
    name: true,
    email: true,
    password: false,
    plan: true,
  },
  errors: {
    password: 'Please lengthen this text to 8 characters or more',
  },
  clear: Function,
  clearField: Function,
  reset: Function,
  resetField: Function,
  setField: Function,
}
Enter fullscreen mode Exit fullscreen mode

It also allow you to initialise it via initialState object, a wide variety of on form event handlers, advanced input options, custom input validation, custom controls and much more. Definitely check their GitHub Repo for more information.

GitHub logo wsmd / react-use-form-state

πŸ“„ React hook for managing forms and inputs state

use-media

This tiny hook is really handy if you're trying to deliver a responsive user experience. It tracks the state of a CSS media query and lets you act on that.

With useEffect:

import useMedia from 'use-media';
// Alternatively, you can import as:
// import {useMedia} from 'use-media';

const Demo = () => {
  // Accepts an object of features to test
  const isWide = useMedia({minWidth: 1000});
  // Or a regular media query string
  const reduceMotion = useMedia('(prefers-reduced-motion: reduce)');

  return (
    <div>
      Screen is wide: {isWide ? 'πŸ˜ƒ' : '😒'}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

With useLayoutEffect:

import {useMediaLayout} from 'use-media';

const Demo = () => {
  // Accepts an object of features to test
  const isWide = useMediaLayout({minWidth: 1000});
  // Or a regular media query string
  const reduceMotion = useMediaLayout('(prefers-reduced-motion: reduce)');

  return (
    <div>
      Screen is wide: {isWide ? 'πŸ˜ƒ' : '😒'}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

For more information about this nifty little hook, visit this GitHub repo.

GitHub logo streamich / use-media

useMedia React hook to track CSS media query state

react-firebase-hooks

I don't have to tell you how great firebase is, but what if you could use a set of hooks to easily integrate with it? It's got 4 set of hooks for you to use:

Usage:

import { useAuthState } from 'react-firebase-hooks/auth';

const CurrentUser = () => {
  const [user, initialising, error] = useAuthState(firebase.auth());
  const login = () => {
    firebase.auth().signInWithEmailAndPassword('test@test.com', 'password');
  };
  const logout = () => {
    firebase.auth().signOut();
  };

  if (initialising) {
    return (
      <div>
        <p>Initialising User...</p>
      </div>
    );
  }
  if (error) {
    return (
      <div>
        <p>Error: {error}</p>
      </div>
    );
  }
  if (user) {
    return (
      <div>
        <p>Current User: {user.email}</p>
        <button onClick={logout}>Log out</button>
      </div>
    );
  }
  return <button onClick={login}>Log in</button>;
};
Enter fullscreen mode Exit fullscreen mode

Of course you don't hard code your username and password right? 😁

Find out more here.

GitHub logo CSFrequency / react-firebase-hooks

React Hooks for Firebase.

use-onClickOutside hook

Many times has happened for me to need to be aware of when the user clicks outside of an element. This might be to change something or perform an action. This little hook allows you to do exactly that:

import * as React from 'react'
import useOnClickOutside from 'use-onclickoutside'

export default function Modal({ close }) {
  const ref = React.useRef(null)
  useOnClickOutside(ref, close)

  return <div ref={ref}>{'Modal content'}</div>
}
Enter fullscreen mode Exit fullscreen mode

As you can see, you can provide a ref to an element and pass it to the hook. If there is a click anywhere outside of the element, the the call-back function, in this case close is called.

Find out more about this hook in this GitHub repo.

GitHub logo Andarist / use-onclickoutside

React hook for listening for clicks outside of an element.

useIntersectionObserver hook

You might remember I did a post on image optimisation and how IntersectionObserver API is a handy tool to load an image lazily when it appears on viewport.

This hook allows you to use this great API:

import React, { useRef, useState } from "react";
import { useIntersectionObserver } from "react-hook-intersection-observer";

const App = () => {
  const root = useRef();    // We need a ref to our "root" or our parent,
  const target = useRef();  // We need a ref to our "target" or our child-to-watch,

  // Let's use a bit of state.
  const [isThingIntersecting, setThingIntersecting] = useState(false);

  // Here's our hook! Let's give it some configuration...
  useIntersectionObserver({
    root,
    target,

    // What do we do when it intersects?
    // The signature of this callback is (collectionOfIntersections, observerElement).
    onIntersect: ([{ isIntersecting }]) => setThingIntersecting(isIntersecting)
  });

  return (
    <div className="App">
      <h1>useIntersectionObserver</h1>
      <h2>
        The thing is currently{" "}

        {!isThingIntersecting && <span style={{ color: "red" }}>not</span>}{" "}

        <span style={{ color: isThingIntersecting ? "green" : "black" }}>
          intersecting
        </span>

        !
      </h2>


      <div ref={root} className="black-box">
        <div className="larger-box">
          <div ref={target}>THE THING</div>
        </div>
      </div>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

To find out more, have a look at this GitHub repo.

GitHub logo TejasQ / react-hook-intersection-observer

A simple React hook that works with the Intersection Observer API.

react-use collection

This is a collection of some great hooks you can use in categories like Sensors, UI, Animations, Side-effects, Lifecycles, and State.

An example is useLocation which gives you the ability to access the location of the browser.

import {useLocation} from 'react-use';

const Demo = () => {
  const state = useLocation();

  return (
    <pre>
      {JSON.stringify(state, null, 2)}
    </pre>
  );
};
Enter fullscreen mode Exit fullscreen mode

If you're using Internet Explorer (but why πŸ˜‚), you can use this polyfill.

Or you can use useBattery to track the battery status on a mobile device:

import {useBattery} from 'react-use';

const Demo = () => {
  const batteryState = useBattery();

  if (!batteryState.isSupported) {
    return (
      <div>
        <strong>Battery sensor</strong>: <span>not supported</span>
      </div>
    );
  }

  if (!batteryState.fetched) {
    return (
      <div>
        <strong>Battery sensor</strong>: <span>supported</span> <br />
        <strong>Battery state</strong>: <span>fetching</span>
      </div>
    );
  }

  return (
    <div>
      <strong>Battery sensor</strong>:&nbsp;&nbsp; <span>supported</span> <br />
      <strong>Battery state</strong>: <span>fetched</span> <br />
      <strong>Charge level</strong>:&nbsp;&nbsp; <span>{ (batteryState.level * 100).toFixed(0) }%</span> <br />
      <strong>Charging</strong>:&nbsp;&nbsp; <span>{ batteryState.charging ? 'yes' : 'no' }</span> <br />
      <strong>Charging time</strong>:&nbsp;&nbsp;
      <span>{ batteryState.chargingTime ? batteryState.chargingTime : 'finished' }</span> <br />
      <strong>Discharging time</strong>:&nbsp;&nbsp; <span>{ batteryState.dischargingTime }</span>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

To find out about all of those, check this GitHub repo.

GitHub logo streamich / react-use

React Hooks β€” πŸ‘

React Redux hooks

React Redux now offers a set of hook APIs as an alternative to the existing connect() Higher Order Component. These APIs allow you to subscribe to the Redux store and dispatch actions, without having to wrap your components in connect().

Here is the useSelector hook returns a part of all of store using a selector function.

import React from 'react'
import { useSelector } from 'react-redux'

export const CounterComponent = () => {
  const counter = useSelector(state => state.counter)
  return <div>{counter}</div>
}
Enter fullscreen mode Exit fullscreen mode

Checkout their comprehensive documentation to find out more.

react-hanger

A set of helpful hooks with focus on primitive types state changing. They have two version, but the recommendation is to use V2.

Install:

yarn add react-hanger
Enter fullscreen mode Exit fullscreen mode

Usage:

import React, { Component } from "react";

import {
  useInput,
  useBoolean,
  useNumber,
  useArray,
  useOnMount,
  useOnUnmount
} from "react-hanger";

const App = () => {
  const newTodo = useInput("");
  const showCounter = useBoolean(true);
  const limitedNumber = useNumber(3, { lowerLimit: 0, upperLimit: 5 });
  const counter = useNumber(0);
  const todos = useArray(["hi there", "sup", "world"]);

  const rotatingNumber = useNumber(0, {
    lowerLimit: 0,
    upperLimit: 4,
    loop: true
  });

  return (
    <div>
      <button onClick={showCounter.toggle}> toggle counter </button>
      <button onClick={() => counter.increase()}> increase </button>
      {showCounter.value && <span> {counter.value} </span>}
      <button onClick={() => counter.decrease()}> decrease </button>
      <button onClick={todos.clear}> clear todos </button>
      <input type="text" value={newTodo.value} onChange={newTodo.onChange} />
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

You can play with these in this CodeSandbox.

Check this GitHub repo for more information.

GitHub logo kitze / react-hanger

A collection of useful React hooks

Summary

I was surprised to find out how many hooks have already being developed by the community to be honest. There are so many and I can't go through all of them here. But if you're hungry for more, check this gem I found which has a collection of tools, hooks, tutorials, videos, podcasts, and more.

Top comments (7)

Collapse
 
ogaston profile image
Omar Gaston Chalas

Just great! this article is a very useful resource.

Collapse
 
dpalyov profile image
Dimitar Palyov

Very nice article, thanks! Definitely going into my list!

Collapse
 
_jezvin profile image
Vincent Jezequel

Thanks for this great list, I'm getting started with the hooks and some of those ones will definitely come in handy !

Collapse
 
sahan profile image
Sahan

Really enjoyed this article. Thank you Yaser! Stoked to see a familiar name popping up on my feed ;)

Collapse
 
yashints profile image
Yaser Adel Mehraban

Thanks mate

Collapse
 
0xbanana profile image
🍌🍌🍌

Thanks Yaser! This is a great list and appreciate you linking the source material!

Cheers!

Collapse
 
yashints profile image
Yaser Adel Mehraban

You’re welcome