如何使用React挂钩重新获取API

时间:2020-03-06 08:15:09

标签: reactjs fetch react-hooks fetch-api

devs

我决定最终学习与我认为简单的项目有关的反应挂钩。我不太清楚如何使用React挂钩重新获取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. 我要么显示“正在加载...”,要么显示初始报价
  4. 我正在尝试设置一个按钮以重新获取API并通过getKanyeQuote(setState)将数据存储在kanyeQuote中

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

错误

非常感谢您可以为此提供任何指导。

1 个答案:

答案 0 :(得分:1)

这里的问题是,您只能在组件根内部直接使用钩子。 这是1号“钩子规则”。您可以了解有关here

的更多信息
  const getMore = () => {
    setKanyeQuote(useFetch(kanye) /* This cannot work! */)
  }

有几种方法可以解决此问题。不知道您的useFetch钩中的内部逻辑,我只能假设您可以更改它。

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

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

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

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

// ...

然后,您需要更改useFetch钩的内部逻辑,以在内部使用useState并公开其吸气剂。看起来像这样:

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

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

  return { data, doFetch };
};

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

如果只想管理父组件中已加载数据的状态,则可以通过挂钩提供包装的访存函数;像这样的东西:

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

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

// ...

然后,您需要更改useFetch钩的内部逻辑,使其不具有任何内部状态,而仅公开包装的提取。看起来像这样:

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

  return doFetch;
};