在React组件中使用自定义hook获取API数据,API响应持续存在

问题描述 投票:0回答:1

我使用钩子来重构可能在多个 React 组件中重复的获取逻辑。钩子本身的逻辑相对通用,映射如下。 它旨在返回响应、潜在错误,并在响应完成后将 isLoading 从 true 更新为 false。

const useFetch = (url, options = {}) => {

  const [response, setResponse] = useState(null);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  console.log("again running useFetch")

  useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch(url, options);
        const json = await res.json();
        setResponse(json);
      } catch (error) {
        setError(error);
      }
      setIsLoading(false);
    };
    fetchData();

  }, []);

  return { response, error, isLoading };
};

现在这是我在 React 组件中使用它的方式,

function CardTable() {

  const [cards, setCards] = useState([]);

  const url = "https://deckofcardsapi.com/api/deck/new/draw/"


  const data = useFetch(url)
  console.log(data.response)
  //{success: true, deck_id: 'mnpedlyiolj7', cards: Array(1), remaining: 51}
  
  const addCard = async () => {
 
    setCards(cards => [...cards, { ...data.response, id: uuid() }]);
  };

它几乎可以工作了,我的理解是数据被分配了在每次渲染我们的 Cardtable 组件时调用我们的 useFetch 钩子函数的值。但是,每次我向 API 发出获取请求时,都会返回相同的响应数据。 我这里一定缺少一些东西,有什么想法吗? 非常感谢您的帮助。

我尝试了多种方法来重新迭代 API 调用,从 API 请求中抽取卡片,但结果仍然相同。这在response.data 的剩余属性中很明显,尽管有多个 API 请求,该属性仍保留并持续在 51。

javascript reactjs object fetch hook
1个回答
0
投票

useFetch
钩子的使用是导致您遇到问题的原因。由于钩子
useEffect
内的
(useEffect(() => {...}, []))
有一个空的依赖数组,因此钩子当前仅在安装
CardTable
组件时调用一次。因此,它在第一次渲染期间仅检索一次数据。

您应该更改

useFetch
挂钩以接受可以更改的参数,从而在必要时(例如,添加新卡时)重新获取。

const useFetch = (url, options = {}) => {
  const [response, setResponse] = useState(null);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  const fetchData = async () => {
    setIsLoading(true);
    try {
      const res = await fetch(url, options);
      const json = await res.json();
      setResponse(json);
    } catch (error) {
      setError(error);
    }
    setIsLoading(false);
  };

  return { response, error, isLoading, fetchData }; // Expose fetchData to trigger re-fetch
};

function CardTable() {
  const [cards, setCards] = useState([]);
  const url = "https://deckofcardsapi.com/api/deck/new/draw/";

  const { response: responseData, fetchData } = useFetch(url); // Destructure the fetchData function

  const addCard = async () => {
    await fetchData(); // Trigger re-fetch when adding a new card
    setCards((prevCards) => [...prevCards, { ...responseData, id: uuid() }]);
  };

  return (
    <div>
      <button onClick={addCard}>Add Card</button>
      {/* Render your card components here */}
    </div>
  );
}

当您想要启动

re-fetch
时(在本例中,在添加卡片时),您可以从
fetchData
挂钩公开
useFetch
方法并显式使用它。这将导致一个新的 API 请求返回更新的数据,使您能够添加具有更新的响应的卡片。

© www.soinside.com 2019 - 2024. All rights reserved.