Improve React Custom Hook Debugging with useDebugValue
Tags: webdev, react, javascript
Published: 2022-06-07 12:47:04

---
title: Improve React Custom Hook Debugging with useDebugValue
published: true
date: 2022-06-02 11:41:21 UTC
tags: webdev, react, javascript
canonical_url: https://www.syncfusion.com/blogs/post/improve-react-custom-hook-debugging-with-usedebugvalue.aspx
cover_image: https://www.syncfusion.com/blogs/wp-content/uploads/2022/06/Improve-React-Custom-Hook-Debugging-with-useDebugValue-672x372.png
---

Improve React Custom Hook Debugging with useDebugValueAs developers, we often need to write complex code to fulfill requirements. However, there’s always a chance that our code may run into errors that prevent it from working as expected.

Traditionally, we use debuggers with IDEs or browser dev tools to debug apps, but when it comes to custom React Hooks, these debugging methods are not very effective. Therefore, we need a different way of debugging custom React Hooks.

This article addresses how to debug custom React Hooks with the [useDebugValue](https://reactjs.org/docs/hooks-reference.html#usedebugvalue "useDebugValue Hook documentation") Hook.

## What is useDebugValue?

[useDebugValue](https://reactjs.org/docs/hooks-reference.html#usedebugvalue "useDebugValue Hook documentation") is a React Hook that allows developers to effectively debug their custom Hooks by assigning custom formatted labels to them. Developers can observe these labels with the help of [React Dev Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en "React Developer Tools Chrome Extension"), which provide insight into the internal logic of the custom Hook to understand its process.

## Defining a custom Hook

Before using the **useDebugValue** Hook, let us first try debugging a custom Hook without anything else.

To do so, let us define a custom Hook **(useFetch)** that fetches data from a given endpoint.

The following code example explains the custom Hook.

```js
import { useCallback, useEffect, useState } from "react"; 

export const useFetch = (url: string) => { 
  const [response, setResponse] = useState<any>(); 
  const [error, setError] = useState<any>();

  const getData = useCallback(async () => { 
    try { 
     const resp = await fetch(url, { 
       method: 'GET', 
       mode: 'cors', 
       headers: { 
            'Content-Type': 'application/json' 
       }, 
     }); 

     const data = await resp.json(); 
     setResponse(data); 
     setStatus(data.success); 
  } catch (err) { 
      setError(err); 
    } 
 }, [url]);

 useEffect(() => { 
  getData(); 
 }, [getData, url]);

 return { response, error };
}
```

This example illustrates the custom React Hook that fetches data from a given endpoint. It has two state variables responsible for holding the response and the error returned from the API. Finally, it returns a JavaScript object to the consumer.

Further, we will consume this Hook in the **App** component to obtain COVID-19 statistics using the COVID-19 API. The following code example elaborates on the use of the custom useFetch Hook.

```js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { useFetch } from './use-fetch'; 

function App() { 
  const fetchedResponse = useFetch('https://www.hpb.health.gov.lk/api/get-current-statistical'); 
  
  return ( 
   <div className="App"> 
     <header className="App-header"> 
       <img src={logo} className="App-logo" alt="logo" /> 
       <p> Edit 
         <code>src/App.tsx</code> 
          and save to reload. 
       </p> 
       <a className="App-link" 
          href="https://reactjs.org" 
          target="_blank"  
          rel="noopener noreferrer" > 
          Learn React 
      </a> 
    </header> 
  </div> 
 );
} 

export default App;
```

When this Hook is observed in React Dev Tools, the state variables and their flow during the Hook’s execution are shown.

![Defining a custom Hook](https://www.syncfusion.com/blogs/wp-content/uploads/2022/06/Defining-a-custom-Hook.png)

In addition, there are a few other issues in monitoring Hooks with React DevTools:

- The content is not readable. To analyze the data variable (output provided by the Hook), we have to break the object tree.
- The content is not understandable at first glance. The Hook and its output data don’t have a label to provide meaningful information.
- The  **Fetch** Hook has no description on it. This makes it hard to understand its purpose.
- React Dev Tools only provide meaningful information on the state variables used by the Hook, not the code written.

This is where **useDebugValue** comes into play. With its help, we can improve the visibility and overall understandability of the code executed within the Hook by providing custom formatted labels.

## Using the useDebugValue Hook

### Step 1: Importing the Hook

You can easily import the useDebugValue Hook from React. Refer to the following code.

```js
import { useDebugValue } from "react";
```

### Step 2: Calling the Hook

We can’t invoke the **useDebugValue** Hook inside another React Hook except within a custom Hook.

To start, observe the **response** state variable by calling the Hook initially and providing the formatting to it so that it is easily interpreted by anyone observing the logs for our custom Hook in React Dev Tools. To do so, invoke the Hook using **useDebugValue().** The Hook requires an object of any type to be passed as the first parameter.  Therefore, the **response** state variable is passed with a message.

Refer to the following code example.

```js
import { useCallback, useDebugValue, useEffect, useState } from "react"; 

export const useFetch = (url: string) => { 
  const [response, setResponse] = useState<any>(); 
  const [status, setStatus] = useState<boolean>(false); 
  const [error, setError] = useState<any>();

  useDebugValue('Success State of API Call: ' + status); 
  useDebugValue('Error State of API Call: ' + error); 
  useDebugValue('Data Returned From API Call: ' + response);

  const getData = useCallback(async () => { 
    try { 
     const resp = await fetch(url, { 
       method: 'GET', 
       mode: 'cors', 
       headers: { 
         'Content-Type': 'application/json' 
       }, 
    }); 
    const data = await resp.json(); 
    setResponse(data); 
    setStatus(data.success); 
   } catch (err) { 
      setError(err); 
     } 
  }, [url]);

  useEffect(() => { 
    getData(); 
  }, [getData, url]);

  return { response, error };
}
```

We see a new state variable, **status,** introduced when observing the updated Hook. This is because React does not allow **useDebugValue** to be called inside another Hook like **useEffect.** So, to access the HTTP response status, another state variable must be used.

### Step 3: Observing the results with the Hook

When the Hook is called and observed in React Dev Tools after setting up **useDebugValue,** the figure shown below can be observed.

![Observing the results with the useDebugValue Hook](https://www.syncfusion.com/blogs/wp-content/uploads/2022/05/Observing-the-results-with-the-Hook.png)

There, we see a new  **DebugValue** array **.** This array outputs all the data we wish to debug in a more readable manner.

**Note** : The indexes of the DebugValue array are printed in sequential order of the calls made to the useDebugValue Hook.

## Optimizing the useDebugValue Hook

Now, the question is, do we need formatting all the time? Isn’t it costly to format data every time a Hook is called or a state within a Hook is changed? The answer to the latter is yes.

However, React has a solution for that, and it is easier than you think! The Hook accepts a second parameter. This parameter is a formatting function that accepts the log data and renders the data only when the Hook is inspected with React Dev Tools, ensuring that the costly formatting operation is not executed every time the Hook is executed.

The following code includes the formatting function in **useDebugValue.**

```js
useDebugValue(response, (res) => {
  // formatting function
  if (res) {
    // format and return the data when hook is inspected.
    return \`Data returned from API that shows local cases for today: ${res.data.local\_new\_cases}\`;
  }
  return 'No Data Returned At The Moment';
});
```

That’s it! We have successfully applied **useDebugValue** in our custom Hook to improve the overall debugging experience.

However, it is always essential to identify when to use this Hook.

## When should you use useDebugValue?

Although **useDebugValue** is really useful, it is not good to include it in all custom Hooks.

The perfect use case of **useDebugValue** is when you have extremely complex code executing in your custom Hook with multiple state variables. Incorporating the **useDebugValue** Hook in a case like this will help filter out unnecessary logging and prioritize your code.

## GitHub reference

Also, refer to the [React custom Hooks debugging with the useDebugValue demo on GitHub](https://github.com/SyncfusionExamples/custom-hook-debugging-with-useDebugValue "React custom Hook debugging with the useDebugValue demo on GitHub").

## Conclusion

This article explored the use of the **useDebugValue** Hook in debugging custom React Hooks. Having the **useDebugValue** in your development arsenal will increase your debugging capabilities for your custom React Hooks.

I hope you have found this useful. Thank you for reading.

The [Syncfusion React](https://www.syncfusion.com/react-ui-components "Syncfusion React UI components") suite offers over 70 high-performance, lightweight, modular, and responsive UI components in a single package. It’s the only suite you’ll ever need to construct a complete application.

If you have questions, you can contact us through our [support forum](https://www.syncfusion.com/forums "Syncfusion support forum"), [support portal](https://support.syncfusion.com/ "Syncfusion support portal"), or [feedback portal](https://www.syncfusion.com/feedback "Syncfusion Feedback Portal"). We are always happy to assist you!