如何使用 React Hooks 重新获取 API

How can I re-fetch an API using react hooks

开发人员,

我决定最终学习 React Hooks,我认为这是一个简单的项目。我不太明白我是如何使用反应挂钩重新获取 API 的。这是我目前的代码。

import React, { useState, useEffect } from "react"
import useFetch from "./utils/getKanya"

const kanye = "https://api.kanye.rest"

const Index = () => {
  let [kanyaQuote, setKanyeQuote] = useState(null)
  let data = useFetch(kanye)

  const getMore = () => {
    setKanyeQuote(useFetch(kanye))
  }

  return (
    <>
      <h1>Welcome to Next.js!</h1>
      <p>Here is a random Kanye West quote:</p>
      {!data ? <div>Loading...</div> : <p>{!kanyaQuote ? data : kanyaQuote}</p>}
      <button onClick={getMore}>Get new quote</button>
    </>
  )
}

export default Index
  1. 我将 kanyeQuote 状态值设为 null
  2. 我获取初始数据
  3. 我显示 "Loading..." 或初始报价
  4. 我正在尝试设置一个按钮来重新获取 API 并通过 getKanyeQuote (setState)
  5. 将数据存储在 kanyeQuote 中

这是我得到的错误 Error: Invalid hook call...

如果您能就此提供任何指导,我将不胜感激。

这里的问题是,您只能直接在组件的根目录中使用挂钩。 这是数字 1 'rule of hooks'。您可以阅读更多相关信息 here

  const getMore = () => {
    setKanyeQuote(useFetch(kanye) /* This cannot work! */)
  }

有几种方法可以解决这个问题。在不知道 useFetch-hook 的内部逻辑的情况下,我只能假设您能够更改它。

更改挂钩以在内部处理其状态

解决此问题的一种方法是更改​​自定义 useFetch 挂钩的逻辑,以提供某种形式的函数来获取数据并在内部更新状态。它可能看起来像这样:

const { data, doFetch } = useFetch(kanye);
useEffect(() => {
  doFetch(); // initialFetch
}, []);

const getMore = () => {
  doFetch();
};

// ...

然后您需要更改 useFetch-hook 的内部逻辑以在内部使用 useState 并公开它的 getter。它看起来像这样:

export const useFetch = (url) => {
  const [data, setData] = useState(null);

  const doFetch = () => {
    // Do your fetch-Logic
    setData(result);
  };

  return { data, doFetch };
};

更改挂钩根本不处理任何状态。

如果只想管理父组件加载数据的状态,可以通过hook提供wrapped fetch函数;类似的东西:

const doFetch = useFetch(kanye);
const [data, setData] = useState(null);
useEffect(() => {
  setData(doFetch()); // initialFetch
}, []);

const getMore = () => {
  setData(doFetch())
};

// ...

然后您需要更改 useFetch-hook 的内部逻辑,使其没有任何内部状态,只公开包装的提取。它看起来像这样:

export const useFetch = (url) => {  
  const doFetch = () => {
    // Do your fetch-Logic
    return result;
  };

  return doFetch;
};