[英]Clean Up code not works correctly in React when using AbortController
我正在使用自定義useHttp
掛鈎從api
獲取一些數據,問題是我想在用戶導航到另一個頁面時中止獲取操作並防止出現奇怪的錯誤。 為此,我在我的鈎子中使用AbortController
API,每當組件unmounts
時,都會觸發該函數。 但是當我的組件渲染時,我會收到一個錯誤,告訴我操作已中止!
掛鈎代碼:
import { useEffect , useState , useCallback , useRef } from 'react';
export const useHttpClient = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState();
const activeHttpRequests = useRef([]);
const sendRequest = useCallback(async (URL, method = 'GET', body = null, headers = {}) => {
setIsLoading(true);
const httpAbortController = new AbortController();
activeHttpRequests.current.push(httpAbortController);
try {
const res = await fetch(URL, {method, body, headers, signal: httpAbortController.signal});
const resData = await res.json();
activeHttpRequests.current = activeHttpRequests.current.filter(reqCtrl => reqCtrl !== httpAbortController)
console.log(activeHttpRequests)
if(!res.ok) {
throw new Error(resData.error);
}
setIsLoading(false)
return resData;
} catch (error) {
setIsLoading(false)
setError(error.message)
throw error;
}
}, [])
const clearError = () => {
setError(null);
}
useEffect(() => {
return () => {
activeHttpRequests.current.forEach(abortCtrl => abortCtrl.abort());
};
}, []);
return {isLoading, error, clearError, sendRequest}
}
這是我組件中的代碼:
// Modules
import React, { useEffect, useState } from 'react';
// Hooks
import { useHttpClient } from '../../../helpers/hooks/http-hook';
// Components
import UserList from '../components/user-list/user-list.component';
import ErrorModal from '../../shared/error-modal/error-modal.component';
import Spinner from '../../shared/loading-spinner/spinner.component';
const Users = () => {
const { isLoading , error , clearError , sendRequest } = useHttpClient();
const [loadedUsers, setLoadedUsers] = useState();
useEffect(() => {
const fetchUsers = async () => {
try {
const URL = 'http://localhost:5000/api/users';
const res = await sendRequest(URL);
setLoadedUsers(res.users);
} catch (error) {}
}
fetchUsers();
}, [sendRequest])
return (
<React.Fragment>
<ErrorModal error={error} onClear={clearError} />
{ isLoading && <Spinner overlay/> }
{ !isLoading && loadedUsers && <UserList users={loadedUsers} /> }
</React.Fragment>
);
}
export default Users;
每當您的組件重新渲染時,上一次渲染中的 useEffect 的清理效果都會在運行下一次渲染中的效果之前運行。 您在組件掛載時調用fetchUsers()
,這會設置setLoadedUsers
,這將導致重新渲染,這將運行您的清理代碼以嘗試取消不存在的請求。
將您的清理代碼更新為此,它應該可以工作
useEffect(() => {
return () => {
if (activeHttpRequests.current.length) {
activeHttpRequests.current.forEach(abortCtrl => abortCtrl.abort());
};
};
}, []);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.