Reactjs 使用异步获取函数对无限循环的使用效果
我试图理解为什么下面的useffect是在一个无限循环中运行的。我使用Reactjs 使用异步获取函数对无限循环的使用效果,reactjs,react-hooks,Reactjs,React Hooks,我试图理解为什么下面的useffect是在一个无限循环中运行的。我使用fetchSchedulehelper函数调用getSchedule服务(使用Axios查询API端点)。我没有在useEffect钩子中定义此函数的原因是,我希望在调用onStatus函数时也调用它(在单独的端点上切换布尔PUT请求) eslinter要求将fetchSchedule添加到依赖项数组中,这似乎触发了无限循环 它的工作方式是在第一次渲染时从数据库获取数据,然后仅在每次更新值道具或切换onStatus按钮时执行
fetchSchedule
helper函数调用getSchedule
服务(使用Axios查询API端点)。我没有在useEffect钩子中定义此函数的原因是,我希望在调用onStatus
函数时也调用它(在单独的端点上切换布尔PUT请求)
eslinter要求将fetchSchedule
添加到依赖项数组中,这似乎触发了无限循环
它的工作方式是在第一次渲染时从数据库获取数据,然后仅在每次更新值
道具或切换onStatus
按钮时执行
到目前为止,我的研究似乎指出,这可能与useEffect在异步函数和闭包中的行为方式有关。我仍在努力理解钩子,很明显,我的代码中有一些东西我没有理解
import React, { useEffect, useCallback } from 'react';
import useStateRef from 'react-usestateref';
import { NavLink } from 'react-router-dom';
import { getSchedule, updateStatus } from '../../services/scheduleService';
import Status from './status';
// import Pagination from './pagination';
const List = ({ value }) => {
// eslint-disable-next-line
const [schedule, setSchedule, ref] = useStateRef([]);
// const [schedule, setSchedule] = useState([]);
const fetchSchedule = useCallback(async () => {
const { data } = await getSchedule(value);
setSchedule(data);
}, [value, setSchedule]);
const onStatus = (id) => {
updateStatus(id);
fetchSchedule();
console.log('fetch', ref.current[0].completed);
};
useEffect(() => {
fetchSchedule();
}, [fetchSchedule]);
return (...)
2021年3月更新 在与回购所有人就
react usestateref
进行合作后,该软件包现在可以按照最初的预期运行,并且可以安全地作为useState
版本1.0.5
的替代品使用。当前的实现如下所示:
function useStateRef(defaultValue) {
var [state, setState] = React.useState(defaultValue);
var ref = React.useRef(state);
var dispatch = React.useCallback(function(val) {
ref.current = typeof val === "function" ?
val(ref.current) : val;
setState(ref.current);
}, []);
return [state, dispatch, ref];
};
如果没有这个
react-usestateref
import,您会很好
钩子返回一个普通的匿名函数来设置状态,这意味着它将在每次渲染时重新创建-您不能有效地将它包含在任何依赖项数组中,因为它也将在每次渲染时更新。但是,由于该函数是从未知的自定义钩子返回的(不管怎样,ESLint都会正确地识别出它不是一个正确的setter函数),因此如果不这样做,就会收到警告
它试图解决的“问题”也会在代码中引入不好的做法——这是一种避免正确处理依赖关系的好方法,因为依赖关系可以使代码更安全
如果你回到一个标准的状态钩子,我相信这段代码会很好的工作。不要试图在状态上获取状态的引用,也要使其异步,并从fetchSchedule返回数据并进行设置
const [schedule, setSchedule] = useState([]);
const fetchSchedule = useCallback(async () => {
const { data } = await getSchedule(value);
setSchedule(data);
return data;
}, [value]);
const onStatus = async (id) => {
updateStatus(id);
const data = await fetchSchedule();
};
useEffect(() => {
fetchSchedule();
}, [fetchSchedule]);
或者,尽管我也不建议使用这个,但我们实际上可以编写一个安全版本的useStateRef钩子:
function useStateRef(defaultValue) {
var [state, setState] = React.useState(defaultValue);
var ref = React.useRef(defaultValue);
ref.current = state;
return [state, setState, ref];
}
状态设置器函数在组件的整个生命周期内始终是引用相同的,因此可以将其包含在依赖项数组中,而不会导致重新创建效果/回调。这个答案可能对您有所帮助?我不确定为什么
useffect()
在你的useStateRef()
hook中,只做var ref=useRef()不是更正确吗;参考电流=状态代码>同步?否则,在渲染阶段完成之前,ref实际上会引用上一个状态。@PatrickRoberts我原来是这样做的,但我改变了它,因为我觉得在渲染完成之前,依赖于状态的任何东西都无法读取它的新值。因此,将ref
与state
绑定在一起,并产生一种效果,将更接近于state的实际工作方式。如果这不是一个很好的理由,我很乐意把它改回去。编辑:虽然我想这并不是为了研究状态实际上是如何工作的……但我确实把它放回去了,因为我确实看到了它是如何更符合钩子的最初目的的。