Как создать кастомный хук, который будет возвращать текущее состояние?

Как можно модифицировать кастомный хук <b>useGetClients</b>, чтобы при его использовании в нескольких компонентах он возвращал одну общую инициализацию, избегая повторных запросов к серверу и дублирования стейтов? Я хотел бы получать загруженных клиентов из разных компонентов без использования Redux и без применения useContext/Provider.
  • 11 октября 2024 г. 9:35
Ответы на вопрос 1
Для реализации кастомного хука `useGetClients`, который будет избегать повторных запросов к серверу и обеспечивать единое состояние, вам необходимо использовать переменные, которые будут храниться вне компонента. Одним из подходов является использование замыкания для хранения состояния клиентов.

Пример реализации такого хука может выглядеть следующим образом:

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

let clientsCache = null;
let isFetching = false;
const fetchClients = async () => {
  const response = await fetch('https://api.example.com/clients'); // Замените на ваш API
  if (!response.ok) {
    throw new Error('Network response was not ok');
  }
  return await response.json();
};

const useGetClients = () => {
  const [clients, setClients] = useState(clientsCache);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      if (clientsCache) {
        setClients(clientsCache);
        return;
      }
      if (isFetching) return; // Если запрос уже идет, ничего не делаем

      isFetching = true;
      setLoading(true);
      
      try {
        const data = await fetchClients();
        clientsCache = data; // Сохраняем в кэш
        setClients(data);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
        isFetching = false; // Сбрасываем флаг после завершения запроса
      }
    };

    fetchData();
  }, []);

  return { clients, loading, error };
};

export default useGetClients;
```

### Как это работает:

1. **Кэширование данных**: `clientsCache` используется для хранения загруженных клиентов. Если данные уже загружены, они извлекаются из кэша, и повторный запрос не выполняется.
   
2. **Флаг `isFetching`**: Этот флаг предотвращает повторные запросы, если запрос уже выполняется.

3. **async/await**: Используется для обработки асинхронного кода с более чистым синтаксисом.

4. **Статус загрузки и ошибки**: Хук также управляет состоянием загрузки и ошибок для компонентов, которые используют этот хук.

### Использование кастомного хука:

Теперь вы можете использовать этот хук в любом компоненте, как показано ниже:

```javascript
import React from 'react';
import useGetClients from './useGetClients';

const ClientList = () => {
  const { clients, loading, error } = useGetClients();

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

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

export default ClientList;
```

Каждый раз, когда вы будете использовать `useGetClients` в разных компонентах, он будет делиться одним и тем же состоянием и запрашивать данные только один раз.
Похожие вопросы