# React: leveraging custom hooks to extract reusable logic

### Scenario: Fetching Data

Instead of repeatedly writing code for data fetching in every component, you can encapsulate that logic in a custom hook. This makes your code **cleaner**, **reusable**, and **easy to maintain**. Let’s walk through a simple example.

### 1\. Create a Custom Hook for Data Fetching

```jsx
import { useState, useEffect } from 'react';

// Custom hook to fetch data
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error('Failed to fetch data');
        }
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;
```

### 2\. Use This Hook in Your Components

Now, you can use `useFetch` in any component to handle API data fetching:

```jsx
import React from 'react';
import useFetch from './useFetch';

function UserList() {
  const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/users');

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error}</p>;

  return (
    <ul>
      {data.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default UserList;
```

### Why This is Useful:

* **Separation of concerns**: The logic for fetching data is separated from the component itself.
    
* **Reusability**: You can use `useFetch` in multiple components without duplicating code.
    
* **Clarity**: Components focus on rendering UI, making them simpler to understand.
    

🔨🤖🔧 **Pro Tip**: Custom hooks can do much more than just fetching data! You can use them for handling form inputs, subscriptions, or even implementing debouncing logic!
