Неверный вызов перехватчика при вызове функции

Я делаю проект React. У меня есть две повторно используемые функции, которые отправляют запросы к API. Когда я вызываю функции, реакция вызывает ошибку:

Ошибка: неверный вызов перехватчика. Хуки можно вызывать только внутри тела функционального компонента. Это может произойти по одной из следующих причин:

  1. У вас могут быть несовпадающие версии React и средства рендеринга (например, React DOM).
  2. Возможно, вы нарушаете правила хуков
  3. У вас может быть более одной копии React в одном приложении.

У меня есть fetchCustomers.jsx:

export default function fetchCustomers() {
  const [customers, setCustomers] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('customers/', {
          headers: {
            'Authorization': `Bearer ${localStorage.getItem('access_token')}`
          }
        });
        setCustomers(response.data);
      } catch (error) {
        console.error("Error al obtener los datos de clientes.", error);
      }
    };

    fetchData();
  }, []);

  return customers;
}

fetchSales.jsx:

export default function fetchSales(params = {}) {
  const [sales, setSales] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('sales/', {
          params: params,
          headers: {
            'Authorization': `Bearer ${localStorage.getItem('access_token')}`
          }
        });
        setSales(response.data.results);
      } catch (error) {
        console.error("Error al obtener los datos de ventas.", error);
      }
    };

    fetchData();
  }, []);

  return sales;
}

и cobrar.jsx:

export default function Cobrar() {
  const [filter, setFilter] = useState({
    startDate: null,
    endDate: null,
    customer: null,
    uncharged: true,
  });
  const [customers, setCustomers] = useState([]);
  const [sales, setSales] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const customersResponse = fetchCustomers();
        setCustomers(customersResponse);
        const salesResponse = fetchSales();
        setSales(salesResponse);
      } catch (error) {
        console.error("Error al obtener los datos.", error);
      }
    }

    fetchData();
  }, []);

Я попробовал вызвать функции в константе, и все работает, но я не могу фильтровать продажи по параметрам. Я хочу получить все продажи, а затем отфильтровать их по диапазону дат и некоторым полям.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

fetchCustomers и fetchSales записываются как хуки, а не как обычные функции. Сначала переименуйте их в useCustomers и useSales (чтобы соответствовать названиям хуков). Затем используйте их в качестве хуков в своем компоненте:

export default function Cobrar() {
  const [filter, setFilter] = useState({
    startDate: null,
    endDate: null,
    customer: null,
    uncharged: true,
  });

  const customers = useCustomers();
  const sales = useSales();

  // the rest of this component...

Вам не нужно повторять использование состояния, поскольку перехватчики сохраняют свое состояние внутри себя.


В качестве альтернативы, если вы не хотите, чтобы эти функции были пользовательскими перехватчиками, удалите их внутреннее использование перехватчиков и просто сделайте их функциями, которые возвращают результаты напрямую. Например:

export default async function fetchCustomers() {

  const response = await axios.get('customers/', {
    headers: {
      'Authorization': `Bearer ${localStorage.getItem('access_token')}`
    }
  });

  return response.data;

}

Затем вы можете вызывать функцию в любом контексте без недопустимого вызова перехватчика, поскольку функция больше не пытается использовать перехватчики.


Общий:

  • Не дублируйте отслеживание данных в состоянии. Синхронизация нескольких источников данных — сложная и ненужная проблема. Отслеживайте состояние компонента или хука, а не того и другого.
  • Хуки можно вызывать только из компонентов или других хуков, и их всегда следует вызывать в одном и том же порядке при рендеринге компонента/хука. Их нельзя вызывать условно, внутри функций и т.д.

Добавляем недостающую часть ответа, по поводу последней части вопроса - если вам нужно проделать какие-то манипуляции с результатами, которые вы получили от хука - создайте еще 1 переменную состояния с хуком useMemo, которая будет отвечать за создание данных, которые вы необходимо отобразить, то есть в вашем случае клонировать результаты перехвата (не изменять результаты перехвата), применить к нему фильтры и т. д. и отобразить этот результат useMemo.

Sergey Sosunov 20.06.2024 16:28

Мне нужно снова вызвать useSales, когда я меняю фильтры, как мне это сделать?

Lucas Leone 20.06.2024 16:33

@LucasLeone: Возможно, самым простым подходом было бы создать эти обычные функции, а не специальные перехватчики. Затем вы можете продолжать поддерживать состояние компонента и повторно вызывать функции в любое время при изменении фильтрации.

David 20.06.2024 16:34

Другие вопросы по теме