解决问题的最佳方法 react-hooks/exhaustive-deps

Best way to resolve react-hooks/exhaustive-deps

这是我的错误:“'setPartData' 函数使 useEffect Hook 的依赖项(第 44 行)在每次渲染时都会发生变化。将它移到 useEffect 回调中。或者,包装 'setPartData'定义到它自己的 useCallback() Hook.eslint(react-hooks/exhaustive-deps)"

我应该如何最好地解决这个问题,因为我无法从数组中删除 url 和 setPartData 并禁用 eslint 规则。

    /* eslint-disable no-shadow */
import { useState, useEffect } from 'react';

export const apiStates = {
    LOADING: 'LOADING',
    SUCCESS: 'SUCCESS',
    ERROR: 'ERROR',
};

/**
 *
 * @param {*} url
 */
export const useApi = (url) => {
    const [data, setData] = useState({
        state: apiStates.LOADING,
        error: '',
        data: [],
    });
    /**
     *
     * @param {*} partialData
     */
    const setPartData = (partialData) => setData({ ...data, ...partialData });

    useEffect(() => {
        setPartData({
            state: apiStates.LOADING,
        });
        fetch(url)
            .then((response) => response.json())
            .then((data) => {
                setPartData({
                    state: apiStates.SUCCESS,
                    data,
                });
            })
            .catch((err) => {
                setPartData({
                    state: apiStates.ERROR,
                    error: err,
                });
            });
    }, [url, setPartData]);

    return data;
};

我尝试使用 useCallBack() 挂钩,但我似乎没有正确实现它,因为我正在创建一个无限循环。任何帮助将不胜感激。

在 useEffect 挂钩中移动 setPartData 的声明,并使用 setData

的函数版本

const setPartData = (partialData) => setData((data) => ({ ...data, ...partialData }));

如果您还需要挂钩之外的 setPartData 函数,请使用 useCallback 使其在每次渲染时都不会更改

const setPartData = useCallback((partialData) => setData((data) => ({ ...data, ...partialData })),[]);

这是完整的 useEffect,其中定义了 setPartData

useEffect(() => {
    /**
     * @param {Partial<typeof data>} partialData
     */
    const setPartData = (partialData) =>
      setData((data) => ({ ...data, ...partialData }));
    setPartData({
      state: apiStates.LOADING,
    });
    fetch(url)
      .then((response) => response.json())
      .then((data) => {
        setPartData({
          state: apiStates.SUCCESS,
          data,
        });
      })
      .catch((err) => {
        setPartData({
          state: apiStates.ERROR,
          error: err,
        });
      });
  }, [url]);