繁体   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