我有一个项目,我创建了一个自定义钩子“useApi”,它管理对我的后端API的调用,以避免每次我需要调用API时重复代码。
这个useApi钩子返回一个数组,第一个参数是加载状态,第二个参数是调用API的函数。
默认情况下,加载状态设置为true,当fetch完成时,加载状态设置为false。
我的问题来了,在某些情况下,我需要调用事件(点击和表单提交)的API。在这种情况下,我会将加载状态默认设置为false,然后在获取之前将其设置为true,并在获取完成时将其设置回false。在下面我的自定义钩子的代码中,我在fetch之前注解了setLoading(true)行,否则会导致无限循环。
我想我有点明白为什么这个无限循环是因为加载状态更新。但是我找不到一个解决方案,如何实现这种“动态”加载状态
import { useState } from "react";
export default function useApi({method, url}) {
const [loading, setLoading] = useState(true);
const abortController = new AbortController();
const fetchBaseUrl = import.meta.env.VITE_APP_URL + '/api/' + url;
const methods = {
get : function(data = {}) {
// setLoading(true);
const params = new URLSearchParams(data);
const queryString = params.toString();
const fetchUrl = fetchBaseUrl + (queryString ? "?"+queryString : "");
return new Promise((resolve, reject) => {
fetch(fetchUrl, {
signal : abortController.signal,
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
},
})
.then(response => response.json())
.then(data => {
setLoading(false);
if (!data) {
return reject(data);
}
resolve(data);
})
.catch(error => {
setLoading(false);
if (!abortController.signal.aborted) {
reject(error);
}
});
});
},
post : function(data = {}) {
// setLoading(true);
const bodyData = {
signal : abortController.signal,
...data
};
return new Promise((resolve, reject) => {
fetch(fetchBaseUrl, {
method: "post",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
},
body: JSON.stringify(bodyData)
})
.then(response => response.json())
.then(data => {
setLoading(false);
if (!data) {
return reject(data);
}
resolve(data);
})
.catch(error => {
setLoading(false);
if (!abortController.signal.aborted) {
reject(error);
}
});
});
}
}
if ( !(method in methods) ) {
throw new Error("Incorrect useApi() first parameter 'method'")
}
return [loading, methods[method]];
}
我尝试的是:
- 使用useRef()钩子替换加载状态:
const loading = useRef(false);
和更新loading.current之前和之后的fetch,但这没有工作,在我的组件,我调用了自定义胡克,加载值接收不更新 - 在具有'data'状态依赖项的useEffect中调用fetch函数(
const [data, setData] = useState({})
),并返回setData而不是fetch函数,也不起作用,setData在某些情况下会进行无限循环(在react-rooter加载器函数中,我有一个无限循环,但在en事件提交事件中没有)
1条答案
按热度按时间laik7k3q1#
在简化了我的自定义钩子之后,我的无限循环错误并不是来自我的setLoading()调用: