Лучший способ разрешить react-hooks / исчерпывающий-deps

#reactjs #react-hooks #usecallback

#reactjs #перехваты реакции #usecallback

Вопрос:

Вот моя ошибка: «Функция ‘setPartData’ изменяет зависимости useEffect Hook (в строке 44) при каждом рендеринге. Переместите его внутрь обратного вызова useEffect. В качестве альтернативы, оберните определение ‘setPartData’ в его собственный useCallback () Hook.eslint(реагирующие крючки / исчерпывающий-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(), но, похоже, я неправильно его реализую, поскольку создаю бесконечный цикл. Любая помощь будет оценена.

Ответ №1:

Переместите ваше объявление setPartData в ловушку useEffect и используйте функциональную версию setData

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

Если вам также нужна функция setPartData вне хука, используйте useCallback , чтобы она не менялась при каждом рендеринге

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

Вот полный эффект использования с 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]);