useEffect React Hook를 사용할 때 누락 된 종속성 경고를 수정하는 방법?


177

React 16.8.6 (이전 버전 16.8.3에서는 좋았 음)으로 가져 오기 요청에서 무한 루프를 방지하려고하면이 오류가 발생합니다.

./src/components/BusinessesList.js
Line 51:  React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array  react-hooks/exhaustive-deps

무한 루프를 멈추는 해결책을 찾지 못했습니다. 사용하지 않고 싶습니다 useReducer(). 가능한 해결책이 내가하는 일에 확신이없는 https://github.com/facebook/react/issues/14920 이 토론을 찾았습니다. You can always // eslint-disable-next-line react-hooks/exhaustive-deps if you think you know what you're doing.그래서 아직 구현을 시도하지 않았습니다.

나는이 현재 설정을 가지고 있습니다 .React hook useEffect는 영원히 / 무한 루프를 계속 실행 하며 유일한 의견은 useCallback()내가 익숙하지 않은 것입니다.

현재 사용중인 방법 useEffect()(와 비슷한 처음에 한 번만 실행하고 싶습니다 componentDidMount())

useEffect(() => {
    fetchBusinesses();
  }, []);
const fetchBusinesses = () => {
    return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  };

답변:


190

효과 외의 다른 곳에서 fetchBusinesses 메서드를 사용하지 않는 경우 단순히 효과로 옮기고 경고를 피할 수 있습니다.

useEffect(() => {
    const fetchBusinesses = () => {
       return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  };
  fetchBusinesses();
}, []);

그러나 렌더링 외부에서 fetchBusinesses를 사용하는 경우 두 가지 사항에 유의해야합니다.

  1. 마운트가 닫힌 상태에서 마운트 중에 사용될 때 메소드로 전달 되지 않는 문제가 fetchBusinesses있습니까?
  2. 메소드가 엔 클로징 클로저에서받는 일부 변수에 의존합니까? 이것은 당신에게 해당되지 않습니다.
  3. 모든 렌더에서 fetchBusinesses가 다시 작성되므로 useEffect로 전달하면 문제가 발생합니다. 따라서 먼저 fetchBusinesses를 종속성 배열에 전달하려면 메모해야합니다.

요약하면 fetchBusinesses외부에서 useEffect사용하는 경우 규칙을 사용 // eslint-disable-next-line react-hooks/exhaustive-deps하지 않도록 설정할 수 있으며 그렇지 않으면 useEffect 내에서 메소드를 이동할 수 있습니다

규칙을 비활성화하려면 다음과 같이 작성하십시오.

useEffect(() => {
   // other code
   ...

   // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) 

14
나는 당신이 잘 설명 한 솔루션을 사용했습니다. 다른 설정으로 인해 다른 곳에서 사용한 다른 솔루션은 useCallback()입니다. 그래서 예를 들면 다음과 같습니다 const fetchBusinesses= useCallback(() => { ... }, [...]) 과는 useEffect()같을 것이다 :useEffect(() => { fetchBusinesses(); }, [fetchBusinesses]);
러스

1
@russ, 맞습니다. 의존 배열에 전달하려면 useCallback을 사용하여 fetchBusiness를 메모해야합니다.
Shubham Khatri

eslint-disable 문을 어디에 둘 것인지 보여 주면 좋을 것입니다. 나는 그것이 useEffect 이상일 것이라고 생각했다
user210757

1
// eslint-disable-next-line react-hooks/exhaustive-deps코드가 정확하다는 것을 린터에게 설명하기 위해 사용 하는 것은 해킹과 같습니다. 나는 그들이 논쟁이 의무적이지 않은 경우를 탐지하기에 충분할 정도로 린터를 더 똑똑하게 만드는 또 다른 해결책을 찾을 것으로 기대한다
Olivier Boissé

1
@TapasAdhikary, 예. 비동기 효과를 사용할 수 있습니다. 효과를 다르게 작성하면됩니다. 확인하시기 바랍니다 stackoverflow.com/questions/53332321/...
하기 Shubham 카트리

75
./src/components/BusinessesList.js
Line 51:  React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array  react-hooks/exhaustive-deps

JS / React 오류는 아니지만 eslint (eslint-plugin-react-hooks) 경고입니다.

hook은 function에 의존한다는 것을 알려주 fetchBusinesses므로 의존성으로 전달해야합니다.

useEffect(() => {
  fetchBusinesses();
}, [fetchBusinesses]);

함수가 다음과 같이 컴포넌트에서 선언되면 렌더링 할 때마다 함수를 호출 할 수 있습니다.

const Component = () => {
  /*...*/

  //new function declaration every render
  const fetchBusinesses = () => {
    fetch('/api/businesses/')
      .then(...)
  }

  useEffect(() => {
    fetchBusinesses();
  }, [fetchBusinesses]);

  /*...*/
}

매번 함수가 새로운 참조로 다시 선언되기 때문에

이 일을하는 올바른 방법은 다음과 같습니다.

const Component = () => {
  /*...*/

  // keep function reference
  const fetchBusinesses = useCallback(() => {
    fetch('/api/businesses/')
      .then(...)
  }, [/* additional dependencies */]) 

  useEffect(() => {
    fetchBusinesses();
  }, [fetchBusinesses]);

  /*...*/
}

또는 그냥 함수를 정의 useEffect

더 : https://github.com/facebook/react/issues/14920


14
새로운 오류가 발생했습니다Line 20: The 'fetchBusinesses' function makes the dependencies of useEffect Hook (at line 51) change on every render. Move it inside the useEffect callback. Alternatively, wrap the 'fetchBusinesses' definition into its own useCallback() Hook
russ

1
이 솔루션은 괜찮 및 기능에 다른 상태를 수정하면 다른 예기치 않은 동작 피하기 위해 dependecies을 추가해야
cesarlarsson을

55

useEffect콜백으로 직접 설정할 수 있습니다 .

useEffect(fetchBusinesses, [])

한 번만 트리거되므로 모든 함수의 종속성이 올바르게 설정되어 있는지 확인하십시오 (을 사용하는 것과 동일 componentDidMount/componentWillMount...)


02/21/2020 수정

완전성을 위해 :

1. useEffect위와 같이 함수를 콜백으로 사용

useEffect(fetchBusinesses, [])

2. 내부 기능 선언 useEffect()

useEffect(() => {
  function fetchBusinesses() {
    ...
  }
  fetchBusinesses()
}, [])

3.와 메모 useCallback()

이 경우 함수에 종속성이 있으면 useCallback종속성 배열 에 포함시켜야 useEffect하며 함수의 매개 변수가 변경되면 다시 트리거됩니다 . 게다가, 그것은 많은 상용구입니다 ... 그래서 그냥 useEffect에서처럼 함수를 전달하십시오 1. useEffect(fetchBusinesses, []).

const fetchBusinesses = useCallback(() => {
  ...
}, [])
useEffect(() => {
  fetchBusinesses()
}, [fetchBusinesses])

4. eslint의 경고를 비활성화

useEffect(() => {
  fetchBusinesses()
}, []) // eslint-disable-line react-hooks/exhaustive-deps

2
나는 당신을 사랑합니다 ...
Nick09

8

솔루션은 반응에 의해 제공되며, useCallback함수의 메모 버전을 반환하는 조언을 사용 합니다.

'fetchBusinesses'함수는 렌더마다 useEffect Hook (NN 라인)의 종속성을 변경합니다. 이 문제를 해결하려면 'fetchBusinesses'정의를 자체 useCallback () Hook react-hooks / exhaustive-deps로 랩핑하십시오.

useCallbackuseEffect차이점은 useCallback이 함수를 반환한다는 차이점 과 동일한 서명 을 갖기 때문에 사용이 간단 합니다. 다음과 같이 보일 것입니다 :

 const fetchBusinesses = useCallback( () => {
        return fetch("theURL", {method: "GET"}
    )
    .then(() => { /* some stuff */ })
    .catch(() => { /* some error handling */ })
  }, [/* deps */])
  // We have a first effect thant uses fetchBusinesses
  useEffect(() => {
    // do things and then fetchBusinesses
    fetchBusinesses(); 
  }, [fetchBusinesses]);
   // We can have many effect thant uses fetchBusinesses
  useEffect(() => {
    // do other things and then fetchBusinesses
    fetchBusinesses();
  }, [fetchBusinesses]);


1

이 기사는 후크로 데이터를 가져 오는 좋은 입문서입니다 : https://www.robinwieruch.de/react-hooks-fetch-data/

기본적으로 페치 함수 정의를 다음과 같이 포함하십시오 useEffect.

useEffect(() => {
  const fetchBusinesses = () => {
    return fetch("theUrl"...
      // ...your fetch implementation
    );
  }

  fetchBusinesses();
}, []);

1

두 번째 인수 유형 배열을 제거 할 수 []있지만 fetchBusinesses()매 업데이트마다 호출됩니다. 원하는 경우 구현에 IF명령문을 추가 할 수 있습니다 fetchBusinesses().

React.useEffect(() => {
  fetchBusinesses();
});

다른 하나는 fetchBusinesses()구성 요소 외부 에서 기능 을 구현하는 것입니다. 의존성 인수를 fetchBusinesses(dependency)호출 에 전달하는 것을 잊지 마십시오 .

function fetchBusinesses (fetch) {
  return fetch("theURL", { method: "GET" })
    .then(res => normalizeResponseErrors(res))
    .then(res => res.json())
    .then(rcvdBusinesses => {
      // some stuff
    })
    .catch(err => {
      // some error handling
    });
}

function YourComponent (props) {
  const { fetch } = props;

  React.useEffect(() => {
    fetchBusinesses(fetch);
  }, [fetch]);

  // ...
}

0

실제로 경고는 후크로 개발할 때 매우 유용합니다. 그러나 어떤 경우에는 당신을 바늘로 can 수 있습니다. 특히 종속성 변경을 수신 할 필요가없는 경우.

fetchBusinesses후크의 종속성 안에 넣지 않으려면 후크의 콜백에 인수로 전달하고 다음 fetchBusinesses과 같이 기본 값을 기본 값으로 설정하면 됩니다.

useEffect((fetchBusinesses = fetchBusinesses) => {
   fetchBusinesses();
}, []);

가장 좋은 방법은 아니지만 경우에 따라 유용 할 수 있습니다.

또한 Shubnam이 작성한 것처럼 아래 코드를 추가하여 ESLint에 후크 확인을 무시하도록 지시 할 수 있습니다.

// eslint-disable-next-line react-hooks/exhaustive-deps

0

처음에 한 번만 [ fetchBusinesses] 를 실행하고 싶습니다.componentDidMount()

fetchBusinesses컴포넌트에서 완전히 빼낼 수 있습니다 .

const fetchBusinesses = () => { // or pass some additional input from component as args
  return fetch("theURL", { method: "GET" }).then(n => process(n));
};

const Comp = () => {
  React.useEffect(() => {
    fetchBusinesses().then(someVal => {
      // ... do something with someVal
    });
  }, []); // eslint warning solved!
  return <div>{state}</div>;
};

이것은 간단한 해결책을 제공 할뿐만 아니라 철저한 경고 경고를 해결합니다. fetchBusiness이제 CompReact 트리 외부의 모듈 범위에 있으므로 테스트를 더 잘하고 쉽게 할 수 있습니다 .

오래된 클로저 범위 ( dep in ) 로 인해 구성 요소에서 초기 소품과 상태 fetchBusinesses만 읽을 수 있기 때문에 외부 재배치 는 여기서 잘 작동합니다 .[]useEffect

함수 의존성을 생략하는 방법

  • 효과 내에서 기능 이동
  • 구성 요소 외부로 기능 이동-(이 기능을 사용하고 있습니다)
  • 렌더링하는 동안 함수를 호출 useEffect하고이 값에 의존하게하십시오 (순수 계산 함수)
  • 뎁을 적용 useCallback하고 최후의 수단으로 감싸는 기능 추가

다른 솔루션과 관련하여 :

당기 fetchBusinesses내부 것은 useEffect()당신이 다른 상태에 액세스하는 경우 정말 도움이되지 않습니다. eslint은 여전히 불평 것 : Codesandbox를 .

나는 또한 eslint 철저한 deps에서 코멘트를 무시하는 것을 피할 것이다. 리팩토링과 의존성 점검을 할 때 잊어 버릴 수 있습니다.


0
const [mount, setMount] = useState(false)
const fetchBusinesses = () => { 
   //function defination
}
useEffect(() => {
   if(!mount) {
      setMount(true);
      fetchBusinesses();
   }
},[fetchBusinesses]);

이 솔루션은 매우 간단하며 es-lint 경고를 무시할 필요가 없습니다. 구성 요소가 마운트되었는지 여부를 확인하기 위해 플래그를 유지하십시오.


0

이 방법으로 시도

const fetchBusinesses = () => {
    return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  };

useEffect(() => {
    fetchBusinesses();
  });

당신을위한 일입니다. 그러나 내 제안은이 방법으로 시도해보십시오. 이전보다 낫습니다. 나는 이런 식으로 사용합니다 :

useEffect(() => {
        const fetchBusinesses = () => {
    return fetch("theURL", {method: "GET"}
    )
      .then(res => normalizeResponseErrors(res))
      .then(res => {
        return res.json();
      })
      .then(rcvdBusinesses => {
        // some stuff
      })
      .catch(err => {
        // some error handling
      });
  };
        fetchBusinesses();
      }, []);

특정 ID의 기초에 데이터를 얻은 [id]다음 콜백 useEffect 를 추가 하면 경고를 표시 할 수 없습니다 React Hook useEffect has a missing dependency: 'any thing'. Either include it or remove the dependency array


-4

다음 줄에 대해 eslint를 비활성화하십시오.

useEffect(() => {
   fetchBusinesses();
// eslint-disable-next-line
}, []);

이런 식으로 구성 요소가 마운트 한 것처럼 사용하고 있습니다 (한 번 호출)

업데이트

또는

const fetchBusinesses = useCallback(() => {
 // your logic in here
 }, [someDeps])

useEffect(() => {
   fetchBusinesses();
// no need to skip eslint warning
}, [fetchBusinesses]); 

fetchBusinesses는 someDeps가 변경 될 때마다 호출됩니다.


비활성화하는 대신이 작업을 수행 [fetchBusinesses]하면 경고가 자동으로 제거되어 문제가 해결되었습니다.
rotimi-best

7
@RotimiBest-이 작업을 수행하면 질문에 설명 된대로 무한 다시 렌더링이 발생합니다.
user210757

나는 실제로 얼마 전에 내 프로젝트 중 하나 에서이 방법을 사용했으며 무한 루프를 생성하지 않았습니다. 그래도 다시 확인하겠습니다.
rotimi-best

@ user210757 대기하지만 서버에서 데이터를 가져온 후 상태를 설정하는 것과 달리 무한 루프가 발생하는 이유는 무엇입니까? 상태를 업데이트하는 경우 함수를 호출하기 전에 if 조건을 작성 useEffect하여 상태가 비어 있는지 확인하십시오.
rotimi-best

@ 로티 미 - 최고의이었다 ahwile I 댓글하지만 난 당신이 useEffect 본체 또는 useCallback로 이동하지 않는 기능은 동일하므로 항상 다시 렌더링 따라서마다 결코 다시 만들어집니다 말할 것 때문에
user210757
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.