Я делаю проект React. У меня есть две повторно используемые функции, которые отправляют запросы к API. Когда я вызываю функции, реакция вызывает ошибку:
Ошибка: неверный вызов перехватчика. Хуки можно вызывать только внутри тела функционального компонента. Это может произойти по одной из следующих причин:
- У вас могут быть несовпадающие версии React и средства рендеринга (например, React DOM).
- Возможно, вы нарушаете правила хуков
- У вас может быть более одной копии 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();
}, []);
Я попробовал вызвать функции в константе, и все работает, но я не могу фильтровать продажи по параметрам. Я хочу получить все продажи, а затем отфильтровать их по диапазону дат и некоторым полям.
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;
}
Затем вы можете вызывать функцию в любом контексте без недопустимого вызова перехватчика, поскольку функция больше не пытается использовать перехватчики.
Общий:
Мне нужно снова вызвать useSales, когда я меняю фильтры, как мне это сделать?
@LucasLeone: Возможно, самым простым подходом было бы создать эти обычные функции, а не специальные перехватчики. Затем вы можете продолжать поддерживать состояние компонента и повторно вызывать функции в любое время при изменении фильтрации.
Добавляем недостающую часть ответа, по поводу последней части вопроса - если вам нужно проделать какие-то манипуляции с результатами, которые вы получили от хука - создайте еще 1 переменную состояния с хуком
useMemo
, которая будет отвечать за создание данных, которые вы необходимо отобразить, то есть в вашем случае клонировать результаты перехвата (не изменять результаты перехвата), применить к нему фильтры и т. д. и отобразить этот результат useMemo.