React useEffect로 로딩 함수를 한 번만 호출하는 방법


210

useEffect는 훅이 모든 변화 기능에 전달 실행할 반응한다. 원하는 속성이 변경 될 때만 호출되도록 최적화 할 수 있습니다.

초기화 함수를 componentDidMount호출하고 변경시 다시 호출하지 않으 려면 어떻게해야 합니까? 엔터티를로드하려고하지만로드 기능에 구성 요소의 데이터가 필요하지 않다고 가정 해 봅시다. useEffect후크를 사용하여 어떻게 만들 수 있습니까?

class MyComponent extends React.PureComponent {
    componentDidMount() {
        loadDataOnlyOnce();
    }
    render() { ... }
}

후크를 사용하면 다음과 같이 보일 수 있습니다.

function MyComponent() {
    useEffect(() => {
        loadDataOnlyOnce(); // this will fire on every change :(
    }, [...???]);
    return (...);
}

답변:


396

useEffect초기 렌더링 이후에 제공된 함수 만 실행하려면 빈 배열을 두 번째 인수로 제공 할 수 있습니다.

function MyComponent() {
  useEffect(() => {
    loadDataOnlyOnce();
  }, []);

  return <div> {/* ... */} </div>;
}

27
또는 데이터 (예 : 사용자 ID)를 가져 오는 데 사용하는 매개 변수가있는 경우 해당 배열의 사용자 ID를 전달할 수 있으며 변경되면 구성 요소가 데이터를 다시 가져옵니다. 많은 유스 케이스가 그렇게 작동합니다.
trixn

4
yep ... 건너 뛰기에 대한 자세한 내용은 다음과 같습니다. reactjs.org/docs/…
Melounek

이것은 가장 간단한 답변처럼 보이지만 ESLint는 불평합니다 ...이 스레드에 대한 다른 답변을 참조하십시오 stackoverflow.com/a/56767883/1550587
Simon Hutchison

loadDataOnlyOnce를 dependencies 배열에 전달하십시오. 작동합니까?
jpmarks

88

TL; DR

useEffect(yourCallback, []) -첫 번째 렌더링 후에 만 ​​콜백을 트리거합니다.

상해

useEffect구성 요소를 렌더링 할 때마다 기본적으로 실행 되므로 효과가 발생합니다.

useEffect컴포넌트에 배치 할 때 리 액트 에 콜백을 실행하고 싶다고 말합니다. 렌더링은 렌더링 후 및 DOM 업데이트를 수행 한 후 효과를 실행합니다.

콜백 만 전달하면 각 렌더링 후에 콜백이 실행됩니다.

두 번째 인수 (배열)를 전달하면 React는 첫 번째 렌더링 후와 배열의 요소 중 하나가 변경 될 때마다 콜백을 실행합니다. 예를 들어 배치 할 때 useEffect(() => console.log('hello'), [someVar, someOtherVar])-콜백은 첫 번째 렌더링 후 someVar또는 그 중 하나 someOtherVar가 변경 되거나 렌더링 된 후에 실행됩니다 .

두 번째 인수에 빈 배열을 전달하면 React는 각 배열을 렌더링 한 후 비교하고 아무것도 변경되지 않았으므로 첫 번째 렌더링 후에 만 ​​콜백을 호출합니다.


69

useMountEffect 훅

컴포넌트 마운트 후 한 번만 함수를 실행하는 것은 구현 세부 사항을 숨기는 자체 후크를 정당화하는 일반적인 패턴입니다.

const useMountEffect = (fun) => useEffect(fun, [])

모든 기능적 구성 요소에서 사용하십시오.

function MyComponent() {
    useMountEffect(function) // function will run only once after it has mounted. 
    return <div>...</div>;
}

useMountEffect 후크 정보

useEffect두 번째 배열 인수와 함께 사용하면 React는 마운트 후 (초기 렌더링) 및 배열의 ​​값이 변경된 후 콜백을 실행합니다. 빈 배열을 전달하므로 마운트 후에 만 ​​실행됩니다.


19
ESLint 규칙 "react-hooks / exhaustive-deps"는 항상 빈 종속성 목록에서 실패하므로 대답을 매우 선호합니다. 예를 들어 유명한 create-react-app 템플릿이 해당 규칙을 적용합니다.
Dynalon

1
@Dynalon에 전적으로 동의합니다. 이것은 ESLint 규칙을 방해하지 않기 때문에 수용된 솔루션이어야합니다
Mikado68

@Dynalon과 Mikado68에게 감사합니다 :-). 결정은 OP의 특권입니다. 귀하의 의견에 대한 알림을 받았지만 OP는 그렇지 않았습니다. 질문에 직접 댓글을 달아 그에게 제안 할 수 있습니다.
벤 잉어

2
지금 당신은 사용할 수 있습니다 useMount: 당신의 효과 기능은 소품에서 무언가를 필요로하지만, 다시 값이 린터의 warnig없이 변경하는 경우에도 실행해야 결코 할 때 useEffect(()=>console.log(props.val),[])없는 의존성 경고를하지만 useMount(()=>console.log(props.val))경고 원인 그러나 "작업을 수행"하지 않습니다. 그래도 동시 모드에 문제가 있는지 확실하지 않습니다.
HMR

1
나는 이것을 좋아한다 :) 이전 상태와 같은 이유; ESLint 규칙은 이것에 대해 불평하지 않으며 빈 배열보다 이해하기 쉽다
Frexuz

20

빈 배열을에 두 번째 인수로 전달하십시오 useEffect. 이것은 효과적으로 React에게 문서를 인용하여 알려줍니다 .

이것은 React에게 효과가 props 또는 state의 값에 의존하지 않으므로 다시 실행할 필요가 없다는 것을 나타냅니다.

다음은 작동한다는 것을 보여주기 위해 실행할 수있는 스 니펫입니다.

function App() {
  const [user, setUser] = React.useState(null);

  React.useEffect(() => {
    fetch('https://randomuser.me/api/')
      .then(results => results.json())
      .then(data => {
        setUser(data.results[0]);
      });
  }, []); // Pass empty array to only run once on mount.
  
  return <div>
    {user ? user.name.first : 'Loading...'}
  </div>;
}

ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>


4

mount함수 를 정의하고 싶습니다. EsLint를 같은 방식으로 속이고 useMount더 자명하다고 생각합니다.

const mount = () => {
  console.log('mounted')
  // ...

  const unmount = () => {
    console.log('unmounted')
    // ...
  }
  return unmount
}
useEffect(mount, [])

-2

트릭은 useEffect가 두 번째 매개 변수를 사용한다는 것입니다.

두 번째 매개 변수는 다시 렌더링하기 전에 구성 요소가 변경되었는지 확인하는 변수의 배열입니다. 여기에 확인하기 위해 원하는 소품과 상태를 넣을 수 있습니다.

또는 아무것도 넣지 마십시오.

import React, { useEffect } from 'react';

function App() {
  useEffect(() => {

    // Run! Like go get some data from an API.

  }, []); //Empty array as second argument

  return (
    <div>
      {/* Do something with data. */}
    </div>
  );
}

그러면 useEffect가 한 번만 실행됩니다.

문서에서 참고하십시오.

이 최적화를 사용하는 경우 시간이 지남에 따라 변경되고 효과에 사용되는 구성 요소 범위 (예 : 소품 및 상태)의 모든 값이 배열에 포함되어 있는지 확인하십시오. 그렇지 않으면 코드에서 이전 렌더링의 오래된 값을 참조합니다.


4
문자 그대로 CSS Tricks에서 복사 / 붙여 넣기를 할 수있는 가장 적은 방법은 소스를 인정하는 것입니다. css-tricks.com/run-useeffect-only-once
버티 쉬
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.