소프트웨어 엔지니어링/프론트 엔드

React 의 useEffect 는 언제 실행될까?

dhsimpson 2022. 12. 30. 01:36

UseEffect 란?

UseEffect 는 함수형 컴포넌트에서 sied effect(callback) 를 실행할 수 있게 도와주는 Hook 이다. (React v16.8 에 추가)

 

즉, 유저가 버튼을 클릭하거나 어떤 상호작용을 통해 컴포넌트 state(변수)가 변경시켰을 때, callback을 수행하도록 할 수 있는 Hook.


UseEffect 가 실행될 때

useEffect 는 다음 상황에 실행된다.

1. 처음 component 가 렌더링 될 때

2. component의 state(변수) 가 변경될 때


Dependancy Array (의존성 배열)

useEffect 는 '어떤 상태(변수)가 변했음'을 감지하고 callback 을 실행시켜 준다.

'어떤 상태' 를 이 useEffect 가 가지는 '의존성' 이라 부르고,

다수의 '상태' 변화를 감지하기 위해 '의존성 배열' 을 useEffect 에게 주입시켜줄 수 있다.


UseEffect 실행을 제어하는 방법

그리고, 위 두 상황을 개발자의 입맛에 맞게 제어하려면 useEffect 메서드의 마지막 파라미터인 dependancy array 를 이용할 수 있다.

 

c.f.)단, 컴포넌트가 렌더링 될 땐 무조건 useEffect 가 실행된다.

 

1. 처음 component 가 렌더링 될 때만 useEffect 실행하도록

  const [show, setShow] = useState(false);
  useEffect(() => {
    alert("CallOnlyFirstRender!!");
  }, []);

useEffect 메서드의 마지막 파라미터를 [] 로 넣으면 '그 어떤 변수의 변화에도 useEffect 를 실행시키지 않을거야!' 라고 하는 것이다.

 

2. 특정 컴포넌트 state(== 변수) 가 변화될 때만 useEffect 실행하도록

  const [show, setShow] = useState(false);
  const [clickCount, setClickCount] = useState(0);
  useEffect(() => {
    alert("CallWhenSpecificStateChange!!");
  }, [clickCount]);

useState 로 show, clickCount 두 개의 state를 생성했다.

show 값을 toggle 하는 버튼을 클릭할 땐 alert 가 발생하지 않고,

clickCount 를 증가시키는 버튼을 클릭할 땐 alert 가 발생하는 것을 볼 수 있다.

 

useEffect 메서드의 마지막 파라미터에 [clickCount] 로 넣으면 'clickCount 상태의 변화에만 useEffect 를 실행시킬 거야!' 라고 하는 것이다.

 

3. 어떤 컴포넌트 변수의 변화에도 useEffect를 실행하도록

  const [show, setShow] = useState(false);
  const [clickCount, setClickCount] = useState(0);

  useEffect(() => {
    alert("CallAnyTime!!");
  });

useState 로 show, clickCount 두 개의 state를 생성했다.

show 값을 toggle 하는 버튼을 클릭할 때에도 alert 가 발생하고,

clickCount 를 증가시키는 버튼을 클릭할 땐 alert 가 발생하는 것을 볼 수 있다.

 

useEffect 메서드의 마지막 파라미터에 아무것도 넣지 않으면, '모든 상태의 변화에 useEffect 를 실행시킬 거야!' 라고 하는 것이다.

 


c.f.) 화면이 렌더링될 때 useEffect 가 두번 실행되는 경우가 발생한다.

이는 CRA 로 설치한 리액트 프로젝트의 index.js(or tsx) 에서 기본적으로 <React.StrictMode> 를 적용시키기 때문인데, 예기치 못한 상황의 에러를 발견할 수 있도록 돕는 기능이다.

렌더링을 두 번 시켜 두 렌더링 결과가 같은지 확인시켜줄 수 있다.

개발 환경에서만 StrictMode가 적용 된다.

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

 

c.f.) useEffect 는 컴포넌트의 렌더링 시에 무조건 실행된다.

그렇다면 컴포넌트가 제거될 때(unmount) 는 무엇을 할 수 있을까?

해당 컴포넌트가 제거될 때, 전역변수 혹은 상위 컴포넌트의 state 를 초기화 시켜줘야 하는 경우가 종종 발생하는데,

이는 useEffect 에 주입 한 메서드의 return 을 통해 수행할 수 있다.(unmount 에 대한 callback 이라 생각하면 된다.)

(A.K.A 이를 clean-up 함수라 부르더라..)

useEffect(() => {
    alert("CallAnyTime!!");
    return ()=> {
        상위컴포넌트_state_초기화();
        recoid_의_전역변수인_Name_값_초기화();
    }
  });

 

c.f.) 클로저(Closure)

useEffect 보단 useState Hook과 관련이 깊은 기술이다.

클로저는 '메서드 내에서 선언한 지역 변수를 메서드 실행이 끝난 이후에도 참조 가능하도록 임시저장 해주는 메모리 공간 ' 이라 생각하면 되는데, 

  const [clickCount, setClickCount] = useState(0);
  useEffect(() => {
    alert("CallWhenSpecificStateChange!!");
  }, [clickCount]);

코드에서 

const [clickCount, setClickCount] = useState(0);

부분에서 클로저가 사용된다.

 

useState 메서드 내부에서 clickCount 와 setClickCount 를

var clickCount = 0;
const setClickCount = (newState)=> {
	clickCount = newState;
}

와 같이 선언하고 return 해 줄 텐데,

useState 내부에서 선언 한 지역변수인 clickCount, setClickCount 를 useState 메서드 실행이 끝났음에도

(지역 변수는 해당 블럭 or 함수 가 끝나면 메모리에서 제거된다.)

클로저를 통해 useEffect 등에서 사용할 수가 있다.

 

 

 

참조 :

- 언제 useEffect 가 실행될까?

https://www.goldencreche.com/blog/when-useeffect-is-called-is-useeffect-called-on-every-render-or-just-the-first-render

- React 공식문서의 useEffect : https://ko.reactjs.org/docs/hooks-effect.html

- unmount callback : https://react.vlpt.us/basic/16-useEffect.html

 - React Hooks 의 동작 원리 : https://it-eldorado.tistory.com/155