Codecademy Logo

Advanced React: Custom Hooks

The Effect Hook

The useEffect hook performs side effects every time a component renders. useEffect accepts two arguments in the form of useEffect(callback, dependencies). The callback argument holds the side-effect logic and is executed every time a render happens.

import React, { useState, useEffect } from 'react';
function TitleCount() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return <button onClick={(prev) => setCount(prev + 1)}>+</button>;
}

Rules for Using Hooks

There are two main rules to keep in mind when using hooks:

  1. Only call hooks from React function components.
  2. Only call hooks at the top level, to be sure that hooks are called in the same order each time a component renders.

Common mistakes to avoid are calling hooks inside of loops, conditions, or nested functions.

// Instead of confusing React with code like this:
if (userName !== '') {
useEffect(() => {
localStorage.setItem('savedUserName', userName);
});
}
// We can accomplish the same goal, while consistently calling our hook every time:
useEffect(() => {
if (userName !== '') {
localStorage.setItem('savedUserName', userName);
}
});

Effect hooks

Effect hooks are useful for performing “side effects” after render such as fetching data and reacting to state changes.

useEffect(() => {
fetch("https://some-api.com/get-some-user-information")
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
});
}, [])

Effect Dependency Array

The dependency array is used to tell the useEffect() method when to call the effect.

  • By default, with no dependency array provided, the effect is called after every render.
  • An empty dependency array signals that the effect never needs to be re-run.
  • A non-empty dependency array signals that the hook runs the effect only when any of the dependency array values changes.
useEffect(() => {
alert('called after every render');
});
useEffect(() => {
alert('called after first render');
}, []);
useEffect(() => {
alert('called when value of `endpoint` or `id` changes');
}, [endpoint, id]);

Custom Hooks

Custom Hooks are JavaScript functions that make use of other hooks, follow the rules of hooks, and whose names begin with use. Custom hooks are simply a convention and the programmer can decide what they do and what they return.

The provided example is from the Playing Hooky project. This custom hook changes the page’s appearance to “dark” or “light” mode while providing the current theme value for use elsewhere in the application.

const useTheme = () => {
// "theme" state with a default value of "light".
const [theme, setTheme] = useState("light");
// Changes the pages CSS styling.
useEffect(() => {
document.documentElement.setAttribute("data-theme", theme);
}, [theme]);
// Function executed in the application.
const onToggleTheme = () => {
setTheme((previousTheme) => previousTheme === "light" ? "dark" : "light");
};
// Makes the function available for use in the application.
return {theme, onToggleTheme};
}

Use of Custom Hooks

Custom hooks have many benefits. They:

  • Allow code to be abstracted
  • Hide complex logic
  • Allow stateful logic to be reused between multiple components

Learn More on Codecademy