7 Interesting React Hooks ⚛️
The introduction of hooks enhanced the way we write React code for state, component lifecycle, and reducer.
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! 🙏