7 Interesting React Hooks ⚛️

The introduction of hooks enhanced the way we write React code for state, component lifecycle, and reducer.

·

6 min read

7 Interesting React Hooks ⚛️

In this article, I present 7 interesting React hooks worth trying out in your React projects.

1. useSound

The useSound hook is one of the most interesting hooks I have found. I have used this hook in my blog — when clicked on the toggle theme [light/dark] icon on the top right in the header. It will make a switch sound 🔊 This hook notches the website one level up 🔥. This hook can be used to notify new incoming messages, for like button and can be used for scrolling also. 😂

Usage

Install the library — npm install use-sound --save and Import — import useSound from 'use-sound';

Example

import useSound from 'use-sound';

import switchOn from '../sounds/siwth-on.mp3';

const Swtich = () => {
  const [play] = useSound(switchOn);

  return <button onClick={play}>Toggle!</button>;
};

2. useDarkMode

The useDarkMode is one of the hooks from the React Recipes 😋 This hook offers to toggle between light ☀️ and dark 🌙 mode of the website theme. After switching the mode, it stores the selected value in a localStorage. The user’s preferred mode will be remembered in the browser until the user explicitly removes it.

Usage

Install the library — npm install react-recipes --save and Import — import { useDarkMode } from "react-recipes";

Example

Basically, useDarkMode() returns two things.

  • darkMode: A boolean value that is true when the dark mode is active.

  • setDarkMode: It toggles between light and dark mode.

import { useDarkMode } from "react-recipes";

const [darkMode, setDarkMode] = useDarkMode();

  return (
    <div className="header">
      <Toggle darkMode={darkMode} setDarkMode={setDarkMode} />
    </div>
  );
}

3. useSpeechRecognition

The useSpeechRecognition hook gives access to the transcript of the speech from the user’s microphone. It uses the Web Speech API under the hood 🙌 This hook can be used to build your own Voice Assistant 🤖

Usage

Install the library — npm install react-speech-recognition --save and Import — import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';

Example

import React from 'react';
import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';

const Dictaphone = () => {
  const {
    transcript,
    listening,
    resetTranscript,
    browserSupportsSpeechRecognition
  } = useSpeechRecognition();

  if (!browserSupportsSpeechRecognition) {
    return <span>Browser doesn't support speech recognition.</span>;
  }

  return (
    <div>
      <p>Microphone: {listening ? 'on' : 'off'}</p>
      <button onClick={SpeechRecognition.startListening}>Start</button>
      <button onClick={SpeechRecognition.stopListening}>Stop</button>
      <button onClick={resetTranscript}>Reset</button>
      <p>{transcript}</p>
    </div>
  );
};
export default Dictaphone;

4. useWhyDidYouUpdate

The useWhyDidYouUpdate makes it easy to see which prop has changed 🤔 that has caused the component to re-render 🔁

Usage

🔗 Hook

function useWhyDidYouUpdate(name, props) {
  // Get a mutable ref object where we can store props ...
  // ... for comparison next time this hook runs.
  const previousProps = useRef();

  useEffect(() => {
    if (previousProps.current) {
      // Get all keys from previous and current props
      const allKeys = Object.keys({ ...previousProps.current, ...props });
      // Use this object to keep track of changed props
      const changesObj = {};
      // Iterate through keys
      allKeys.forEach((key) => {
        // If previous is different from current
        if (previousProps.current[key] !== props[key]) {
          // Add to changesObj
          changesObj[key] = {
            from: previousProps.current[key],
            to: props[key],
          };
        }
      });
      // If changesObj not empty then output to console
      if (Object.keys(changesObj).length) {
        console.log("[why-did-you-update]", name, changesObj);
      }
    }
    // Finally update previousProps with current props for next hook call
    previousProps.current = props;
  });
}

Example

import { useState, useEffect, useRef } from "react";

// Let's pretend this <Counter> component is expensive to re-render so ...
// ... we wrap with React.memo, but we're still seeing performance issues :/
// So we add useWhyDidYouUpdate and check our console to see what's going on.
const Counter = React.memo((props) => {
  useWhyDidYouUpdate("Counter", props);
  return <div style={props.style}>{props.count}</div>;
});

function App() {
  const [count, setCount] = useState(0);
  const [userId, setUserId] = useState(0);
  // Our console output tells use that the style prop for <Counter> ...
  // ... changes on every render, even when we only change userId state by ...
  // ... clicking the "switch user" button. Oh of course! That's because the
  // ... counterStyle object is being re-created on every render.
  // Thanks to our hook we figured this out and realized we should probably ...
  // ... move this object outside of the component body.
  const counterStyle = {
    fontSize: "3rem",
    color: "red",
  };
  return (
    <div>
      <div className="counter">
        <Counter count={count} style={counterStyle} />
        <button onClick={() => setCount(count + 1)}>Increment</button>
      </div>
      <div className="user">
        <img src={`http://i.pravatar.cc/80?img=${userId}`} />
        <button onClick={() => setUserId(userId + 1)}>Switch User</button>
      </div>
    </div>
  );
}

5. usePrevious

The usePrevious hook stores the previous values internally using the refs. This hook can be used in a use case where there is a undo button.

Usage

🔗 Hook

function usePrevious(value) {

  // The ref object is a generic container whose current property is mutable ...
  // ... and can hold any value, similar to an instance property on a class
  const ref = useRef();

  // Store current value in ref
  useEffect(() => {
    ref.current = value;
  }, [value]); // Only re-run if value changes
  // Return previous value (happens before update in useEffect above)
  return ref.current;
}

Example

import { useState, useEffect, useRef } from "react";

function App() {
  // State value and setter for our example
  const [count, setCount] = useState(0);
  // Get the previous value (was passed into hook on last render)
  const prevCount = usePrevious(count);
  // Display both current and previous count value
  return (
    <div>
      <h1>
        Now: {count}, before: {prevCount}
      </h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

6. useOnClickOutside

The useOnClickOutside hook is used to detect the clicks outside of an element, This hook will be very useful for closing a modal when clicked outside the modal, closing the dropdown when it’s open.

Usage

Install the library npm install use-onclickoutside --save Import — import useOnClickOutside from 'use-onclickoutside';

Example

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>
}

7. useTheme

The useTheme hook makes it easy to dynamically change the appearance of your app using the CSS variables. This is a lightweight alternative to styled-components or any other CSS-in-JS framework. In this hook, simply pass in an object containing key/value pairs of the CSS variables that need to update and the hook updates each variable in the document’s root element. Check out the CodeSandbox demo for a more interesting example and also check out the stylesheet.

Usage

🔗 Hook

function useTheme(theme) {
  useLayoutEffect(
    () => {
      // Iterate through each value in theme object
      for (const key in theme) {
        // Update css variables in document's root element
        document.documentElement.style.setProperty(`--${key}`, theme[key]);
      }
    },
    [theme] // Only call again if theme object reference changes
  );
}

Example

function useTheme(theme) {
  useLayoutEffect(
    () => {
      // Iterate through each value in theme object
      for (const key in theme) {
        // Update css variables in document's root element
        document.documentElement.style.setProperty(`--${key}`, theme[key]);
      }
    },
    [theme] // Only call again if theme object reference changes
  );
}

Thanks for taking the time to read this article! 🙏