React 自定义 Hook - useFetch

2025-05-28

React 自定义 Hook - useFetch

如果你想看的话,我有一个 YouTube 视频😎🍿。

为什么要使用Fetch?

当用户访问某个页面时获取数据是很常见的。我们在获取这些数据时也使用通用的逻辑。

我们的组件中还包含大量的样板/逻辑,而且不太符合 DRY(不要重复自己)。

这些都是创建自定义钩子的理由。我们可以将这些样板/逻辑外包到一个单独的文件中。该文件将保存函数(钩子),该函数将返回我们在组件中需要使用的内容。

旧方法

在这个例子中,我将使用useState钩子来跟踪加载状态、任何错误以及数据。我将使用useEffect钩子来运行所有这些代码。最后,我使用 axios 来获取数据,并使用取消令牌来取消任何我们不再需要的未完成请求。

//App.js
import { useState, useEffect } from 'react';
import axios from 'axios';
import './App.css';

function App() {
  const [quote, setQuote] = useState(null);
  const [loading, setLoading] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
      setLoading('loading...')
      setQuote(null);
      setError(null);
      const source = axios.CancelToken.source();
      axios.get('https://api.quotable.io/random', { cancelToken: source.token })
      .then(res => {
          setLoading(false);
          setQuote(res.data.content);
      })
      .catch(err => {
          setLoading(false)
          setError('An error occurred. Awkward..')
      })
      return () => {
          source.cancel();
      }
  }, [])

  return (
    <div className="App">
      <button onClick={fetchQuote}>Fetch Quote</button>
      { loading && <p>{loading}</p> }
      { quote && <p>"{quote}"</p> }
      { error && <p>{error}</p> }
    </div>
  )
}

export default App;
Enter fullscreen mode Exit fullscreen mode

代码太多了。我们把大部分代码移走。

新方法

我们将创建另一个名为 的文件useFetch.js。您需要以“use”开头自定义钩子的名称,以便 React 知道将其视为钩子。

让我们复制 import 语句、所有 3 个 useStates 和 useEffect 函数。

//useFetch.js
import { useState, useEffect } from 'react';
import axios from 'axios';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
      setLoading('loading...')
      setData(null);
      setError(null);
      const source = axios.CancelToken.source();
      axios.get(url, { cancelToken: source.token })
      .then(res => {
          setLoading(false);
          //checking for multiple responses for more flexibility 
          //with the url we send in.
          res.data.content && setData(res.data.content);
          res.content && setData(res.content);
      })
      .catch(err => {
          setLoading(false)
          setError('An error occurred. Awkward..')
      })
      return () => {
          source.cancel();
      }
  }, [url])

  return { data, loading, error }

export default useFetch;
Enter fullscreen mode Exit fullscreen mode

你可能注意到了一些变化。首先,这个函数(也就是我们的钩子)名为 useFetch。它接收一个参数,该参数是我们想要从中获取数据的 URL。

我们还将其改为setQuotesetData使其更加灵活。请注意,我们还会检查多个响应,以使其更加灵活。

最后,我们的 useFetch 函数(钩子)返回我们的数据、加载和任何错误。

我把它们放在一个对象中,这样我们就可以在组件中访问它们时使用对象解构。这样,解构它们的顺序就无关紧要了,而且我们可以根据需要重命名它们。接下来我会演示这一点。

在我们的组件中使用 useFetch

回到我们的 App 组件,我们将从 导入 useFetch 钩子useFetch.js,并传入我们想要获取数据的 URL。我们将使用对象解构来访问所需的数据。最后,我们将 data 重命名为 quote。

import useFetch from './useFetch';
import './App.css';

function App() {
  const { data: quote, loading, error } = useFetch('https://api.quotable.io/random')

  return (
    <div className="App">
      { loading && <p>{loading}</p> }
      { quote && <p>"{quote}"</p> }
      { error && <p>{error}</p> }
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

非常干净😎。

结论

自定义 hooks 对于简化代码非常有用。你可以在自定义 hooks 中使用 React hooks(毕竟它们都是函数!👍)。你可以封装大量重复的逻辑,然后从自定义 hooks 中返回所需的内容。

如果您喜欢了解类似的主题,请随时查看我的YouTubeInstagram

希望这对某人有帮助,感谢您的阅读!

-安德鲁

文章来源:https://dev.to/techcheck/custom-react-hook-usefetch-eid
PREV
区块链 101(以及使用它的协议)
NEXT
如何在 React 中使用 Storybook