DEV Community

jkap100
jkap100

Posted on • Updated on

Custom Hooks in React

** REACT HOOKS**

Hooks were introduced in React 16.8 which let you use state and other React features without needing to write a class. The primary reason for introducing hooks was to solve a wide range of problems including:

  • It's hard to reuse stateful logic between components

  • Complex components become difficult to understand

  • Classes confuse both people and machines

A detailed explanation of these issues are discussed within React Docs

React has create a number of useful hooks that are ready for use (useState, useEffect etc.). If you are interested in learning more about built in React hooks reference here.

CUSTOM HOOKS

Often times it is desirable to use the same stateful logic between multiple components. Traditionally this has been achieved by having higher-order components and then rendering props. Creating custom hooks allows for the use of the same stateful logic but without the requirement of adding additional components.

When creating a custom hook the first thing that you need to do is give the hook a name that begins with "use". This is a convention used by React so that React can perform behind the scenes work to ensure your code will perform as expected.

CREATING OUR OWN CUSTOM HOOK

Let's walk through an example of creating a custom hook that will fetch data and can be reusable across multiple components.

To begin I have created a very simple React app that has only an App and Index component. It also will utilize a JSON server to fetch data from a db.json. Currently in App we have imported useEffect and useState and wrote a function that will fetch all of the images in our database. Here is the code.

import "./App.css";
import React, { useState, useEffect } from "react";

function App() {
   const baseUrl = "http://localhost:3001";

   const [images, setImages] = useState([]);

   useEffect(() => {
     fetch(baseUrl + "/images")
      .then((r) => r.json())
      .then(setImages);
   }, []);

   return (
     <div>
       <h1>Fetch Data</h1>
     </div>
   );
 }

export default App;
Enter fullscreen mode Exit fullscreen mode

Inspecting the console will show that the array of image objects has successfully been fetched and stored in state.

Image description

The first step to building the custom hook is to create a new component where we will writ code to create the custom hook which I have will call useFetch.js. Make sure to import useState and useEffect.

A way to save a little time getting started writing the code for useFetch is to copy the code we have in the App component and then make updates so that it will be reusable. Replace images and setImages with data and setData. This allows for the ability to fetch different types of data during future use. You may be wondering if calling both the useState and arrow function parameters "data" will cause an issue. It does not as the arrow function parameter is local inside the function.

The next step is to return some values from the useFetch function. To do this create an object and place data inside of it. In this examples only have one value to include however in other uses it is possible to include multiple values within the object in order to achieve the desired results from the hook thats being written.

The last thing to do is pass the endpoint of the url into the usFetch function. This also means that the url needs to be set as a dependency to useEffect. To do so add it to the array. What this means is that whenever the url changes it will re-run the function to fetch the data. Now we are done with useFetch.js. Here is the code:

function useFetch(url) {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch(url)
     .then((r) => r.json())
     .then(setData);
 }, [url]);

  return { data };
}

export default useFetch;
Enter fullscreen mode Exit fullscreen mode

Now it is time to import the useFetch function inside the Aoo component and use it. At the top of app import useFetch from "./useFetch". Inside the app function se data as a variable equal to useFetch and pass in the url. It looks like this:

import "./App.css";
import React, { useState, useEffect } from "react";
import useFetch from "./useFetch";

function App() {
   const data = useFetch"http://localhost:3001/images";

   return (
     <div>
       <h1>Fetch Data</h1>
     </div>
   );
 }

export default App;
Enter fullscreen mode Exit fullscreen mode

Now going back and inspecting the console it would show you the Fetch hook and images have been successfully fetched and stored in state

Image description

CONCLUSION

A huge benefit of custom hooks is reusability. When written and used properly they can eliminate writing the same code across multiple components that use the same common stateful logic. If you want to learn more about building your own custom hooks visit here

Oldest comments (0)