【发布时间】:2021-10-23 06:10:57
【问题描述】:
我试图从事件处理程序(基本上是 onClick)每次渲染只调用一次 axios 调用,所以我使用 useEffect 并且在该 useEffect 内部,我使用的是 useState。问题是 - 调用 onClick 时,出现以下错误:
错误:无效的挂钩调用。 Hooks 只能在函数组件内部调用。
我明白我为什么会得到它,我在事件处理程序中使用 useState - 但我不知道还能做什么。如果没有 useState,我还能如何处理这些变量?
HttpRequest.js
import {useEffect, useState} from 'react'
import axios from 'axios'
export function useAxiosGet(path) {
const [request, setRequest] = useState({
loading: false,
data: null,
error: false
});
useEffect(() => {
setRequest({
loading: true,
data: null,
error: false
});
axios.get(path)
.then(response => {
setRequest({
loading: false,
data: response.data,
error: false
})
})
.catch((err) => {
setRequest({
loading: false,
data: null,
error: true
});
if (err.response) {
console.log(err.response.data);
console.log(err.response.status);
console.log(err.response.headers);
} else if (err.request) {
console.log(err.request);
} else {
console.log('Error', err.message);
}
console.log(err.config);
})
}, [path])
return request
}
RandomItem.js
import React, {useCallback, useEffect, useState} from 'react';
import Item from "../components/Item";
import Loader from "../../shared/components/UI/Loader";
import {useAxiosGet} from "../../shared/hooks/HttpRequest";
import {useLongPress} from 'use-long-press';
function collectItem(item) {
return useAxiosGet('collection')
}
function RandomItem() {
let content = null;
let item;
item = useAxiosGet('collection');
console.log(item);
const callback = useCallback(event => {
console.log("long pressed!");
}, []);
const longPressEvent = useLongPress(callback, {
onStart: event => console.log('Press started'),
onFinish: event => console.log('Long press finished'),
onCancel: event => collectItem(),
//onMove: event => console.log('Detected mouse or touch movement'),
threshold: 500,
captureEvent: true,
cancelOnMovement: false,
detect: 'both',
});
if (item.error === true) {
content = <p>There was an error retrieving a random item.</p>
}
if (item.loading === true) {
content = <Loader/>
}
if (item.data) {
return (
content =
<div {...longPressEvent}>
<Item name={item.data.name} image={item.data.filename} description={item.data.description}/>
</div>
)
}
return (
<div>
{content}
</div>
);
}
export default RandomItem;
它可以很好地加载第一个项目,但是当您尝试取消长按(基本上是 onClick 事件处理程序)时,它会吐出上面的错误。
【问题讨论】:
-
@T.J.Crowder 我同意这很复杂,但我认为我有一个目标:这完全是关于 longPressEvent -> onCancel -> collectItem -> useAxiosGet 链。所以事件处理程序仅在某些事件发生后才尝试实例化钩子(
onCancel) -
@skyboyer 这正是发生的事情,你长按一个 div,如果你不按住点击,onCancel 会被调用。 onCancel 调用 collectItem 并调用 useAxiosGet。 onCancel 本质上只是一个 onClick 事件处理程序。问题仅在于从事件处理程序调用的 useAxiosGet 函数。
-
@skyboyer - 啊,很好看。乔恩,minimal reproducible example 会让这很多更清楚。
-
不是在
useEffect钩子中处理所有这些,您可以创建一个函数,在该函数内部处理它,然后返回该函数以及自定义useAxiosGet中的所有数据钩。 Here's an example of how it can be done
标签: javascript reactjs