簡體   English   中英

React.js 自定義獲取掛鈎中的錯誤

[英]Bug in React.js custom fetch hook

我的 React (v18.1.0) 項目中有以下自定義掛鈎useFetch ,用於從 Node.js 服務器獲取數據。

export default function useFetch(url, requestType, headers, body) {
  const [error, setError] = useState(false);
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  console.log('Inside useFetch hook');
  useEffect(() => {
    console.log('Inside useEffect in the useFetch hook');
    const controller = new AbortController();
    async function retrieveData(reqUrl) {
      try {
        console.log('Inside the useFetch try block');
        const res = await fetchData(
          reqUrl,
          requestType,
          headers,
          body,
          controller.signal
        );
        console.log('Done with fetch; this is the server response ', res);
        setData(res);
        setLoading(false);
        console.log('Done with useFetch try block.');
      } catch (err) {
        if (err.name === 'AbortError') {
          console.log('Fetch aborted');
        } else {
          setError(true);
          setData(err);
          setLoading(false);
        }
      }
    }
    retrieveData(url);
    return () => {
      controller.abort();
    };
  }, []);
  return { loading, error, data };
}

我的 useFetch 掛鈎使用名為fetchData的 function 向服務器發送提取請求。

async function fetchData(url, requestType, headers, payload, abortSignal) {
  console.log('Inside the fetch function');
  let res = await fetch(url, {
    method: requestType,
    headers: headers,
    body: payload,
    signal: abortSignal ? abortSignal : null,
  });
  if (res.ok) {
    const resJson = await res.json();
    console.log('Returning value from fetch function');
    return { status: res.status, response: resJson };
  } else {
    await fetchErrorHandler(res);
  }
}

useFetch掛鈎在我的VideoPlayer組件中被調用一次。

function VideoPlayer() {
  const { videoId } = useParams();
  const url = `http://localhost:5000/videos/${videoId}`;
  const { loading, error, data } = useFetch(url, 'GET', {}, null);

  return (
    <div>
      {loading && <div />}
      {!loading && error && <h2>{data.message}</h2>}
      {!loading && !error && (
        <video width={600} height={450} controls src={data.response.videoUrl}>
          Cannot display video player.
        </video>
      )}
    </div>
  );
}

我面臨的問題是,當VideoPlayer組件掛載到 DOM 並useFetch時,執行流程如下所示: Execution flow of useFetch hook 如圖所示,在控制台打印Inside the fetch function行之前,一切似乎都很好。 此后,再次調用useFetch中的useEffect掛鈎,原因我無法理解(我的依賴項數組為空,而且此時沒有 state 更改)。 然后,它嘗試再次執行fetch ,中止它,然后最終返回一個響應,大概是對原始fetch請求的響應。 在此過程結束時,將再次調用useFetch 如果有人能幫助我闡明為什么掛鈎會以這種方式運行,而不是簡單地執行一次fetch請求並返回響應,我將不勝感激。

我假設您在StrictMode中使用 React - 這是使用 create-react-app 創建的應用程序的默認設置。

在嚴格模式下,效果可以在開發模式下觸發兩次 您可以通過運行生產構建來驗證這是否會導致您的問題。 如果問題消失,則可能是由 StrictMode 引起的。

我的建議是不要更改任何東西——實際上,您的代碼似乎工作正常:第一個效果執行觸發一次提取,然后第二個效果執行中止初始提取並進行第二次提取。 這正是代碼預期執行的操作。

可以用axios來處理API

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM