如何在自定义钩子中修复“ useEffect缺少依赖项”

时间:2019-10-16 12:48:22

标签: reactjs eslint react-hooks use-effect

我正在使用自定义钩子来从API中提取一些数据,以便在一组React函数组件中使用。但是,esLint会发出一个可爱的警告:

  

反应挂钩useEffect缺少依赖项:'fetchFromAPI'。要么   包括它或删除依赖项数组。

我不认为这是依赖项,因为它位于useFetch()内部。我在使用await时需要这样做。我究竟做错了什么?可以仅关闭此行的警告吗?还是我应该使用更规范的语法?

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

  async function fetchFromAPI() {
    const json = await( await fetch(url) ).json();
    setData(json);
  }

  useEffect(() => {fetchFromAPI()},[url]);

  return data;
};

export {
  useFetch
};

4 个答案:

答案 0 :(得分:2)

通过将url作为参数并将return json设置在useEffect内,在自定义效果之外进行声明

async function fetchFromAPI(url) {
    const json = await( await fetch(url) ).json();
    return json
}

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

  useEffect(() => {
      setData(fetchFromAPI(url))
  },[url]);

  return data;
};

或直接在useEffect

内部
function useFetch (url) {
  const [data, setData] = useState(null);

  useEffect(() => {
      async function fetchFromAPI() {
         const json = await( await fetch(url) ).json();
         return json
      }
      setData(fetchFromAPI())
  },[url]);

  return data;
};

答案 1 :(得分:2)

我建议您在useEffect自身内部定义异步函数:

function useFetch (url) {
  const [data, setData] = useState(null);
  useEffect(() => {
    async function fetchFromAPI() {
      const json = await( await fetch(url) ).json();
      setData(json);
    }
    fetchFromAPI()
  },[url]);

  return data;
};

您可以查看doc faqs中的有效示例,该示例在useEffect自身内部使用异步函数:

function ProductPage({ productId }) {
  const [product, setProduct] = useState(null);

  useEffect(() => {
    // By moving this function inside the effect, 
    // we can clearly see the values it uses.
    async function fetchProduct() {
      const response = await fetch('http://myapi/product' + productId);
      const json = await response.json();
      setProduct(json);
    }

    fetchProduct();
  }, [productId]); // ✅ Valid because our effect only uses productId
  // ...
}

答案 2 :(得分:1)

只需将函数移到useEffect内,一切都会好起来的

import { useState, useEffect } from "react";

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

  useEffect(() => {
    async function fetchFromAPI() {
      const json = await (await fetch(url)).json();
      setData(json);
    }
    fetchFromAPI();
  }, [url]);

  return data;
}

export { useFetch };

https://codesandbox.io/s/clever-cdn-8g0me

答案 3 :(得分:1)

async function fetchFromAPI(url) {
  return ( await fetch(url) ).json();
}

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

  useEffect(() => {
    fetchFromAPI(url).then(setData);
  }, [url, setData, fetchFromAPI]);

  return data;
};

export {
  useFetch
};
  1. 您可以稍作更改然后提取fetchFromAPI,因为每次使用useFetch调用时都不会创建它,这对于单一职责也很有益。
  2. 如果您很好地理解了此代码,则可以关闭当前行的lint,也可以添加其余的setDatafetchFromAPI参数。并完全按此顺序。因为在重新渲染参数时比较是从第一个参数到最后一个参数进行比较,最好将变化最大的参数放在第一位,以免每次更改下一个参数时都不检查未变化的参数,因此如果useEffect首先被更改,则不要不需要检查其他对象并更早调用传递的函数