React Hooks

What are Hooks?

Hooks make it easy to reuse stateful logic - code that uses a state(an object used to contain data or information about a component) between components. This feature makes it possible to reuse hooks among multiple components. The introduction of hooks made it easier to maintain and understand large codebases as they allow components to be split into smaller functions and are paired with one another based on the similarity of their operations.

Rules of Hooks

There are two rules to be followed when making use of hooks. Although React has a way of enforcing these rules automatically, it is in our best interest to know these rules as it makes it easier to identify misuse:

  • Hooks should only be called at the top level Hooks should only be called at the top level of a React Component. This ensures the hooks are called in the same order when a component re-renders. Hooks should not be called in loops or conditions as it affects the order in which they are called during component re-rendering.
  • Hooks should only be called from React Functions or Custom Hooks.

Example of Hooks

A popular and frequently used hook is the useState hook. Its usage is similar to how array destructuring works in vanilla JavaScript. The useState hook returns an array containing two items. The first item is called the "current state" which is the initial state(value) we provide. The second item is a function that allows you to change the "current state" to any other value in response to an event. These items can be called anything you want. Although, it is best practice to give the items related names and start the second item with "set":

import { useState } from 'react';

const ButtonClick = () => {
    // count => current state
    // setCount => function
    const [ count, setCount ] = useState(0); 
    function handleClickCount() => setCount(count + 1);
    return (
      <div>
          <p> You clicked { count } times </p>
          <button onClick={handleClickCount}> Click me </button>
      </div>
   );
}

Creating Custom Hooks

We can see from the previous example that hooks are reusable functions. There are situations where we have a logic that we need to use in multiple components. An approach would be to paste that logic in a component where it would be needed, but that would make our code unnecessarily lengthy, and hard to understand and maintain. A better approach would be to create a custom hook. This is done by extracting the logic and placing it in its own component where it can be called when needed. Custom Hooks usually start with "use":

function App() {

  //function to log value of element clicked on
  const handleClick = (e) => console.log(e.target.value);

  return (
    <div>
      <button type="button" onClick={handleClick}>
        Hello
      </button>
    </div>
  );
}

export default App;

We now make the handleClick function a custom hook and then use it in the App Component:

import { useState } from "react";

//custom hook => useConsole
export const useConsole = (value) => {      
  function handleClick(e) {
    console.log(e.target.value);
  }
  return  [handleClick];
}

function App() {
  //from custom hook
  const [ handleClick ] = useConsole();

  return (
    <div>
      <button type="button" onClick={(e) => handleClick(e)}>
        Hello
      </button>
    </div>
  );
}