[TIL / React] Side Effect(부차 작용)의 관리는 useEffect로

알락·2022년 10월 12일
0

React

목록 보기
4/4

React Logo

Component Lifecycle(컴포넌트 생명주기)

Component Lifecycle

사진출처 : 리액트 공식문서

  1. Mount(생성 될 때) - "컴포넌트가 만들어지고 DOM에 삽입될 때"
  2. Update(업데이트 할 때) - "컴포넌트가 업데이트될 때"
  3. Unmount(제거 할 때) - "컴포넌트가 DOM에서 해제될 때 혹은 제거 될 때"

리액트 컴포넌트에는 생명주기가 있다. 컴포넌트는 위에 정리된 각 단계를 순서대로 지나게 된다. 클래스 컴포넌트를 사용할 때는 constructorcomponentDidMount, componentDidUpdate 같은 메소드로 생명주기를 구현할 수 있었는데 Hook을 사용한 함수 컴포넌트에서는 그 과정을 간략하게 만들었다. 이번에 다루는 Hook useEffect는 "Update"단계와 "Unmount"단계가 관련이 있다.


Side Effect(부차 작용)

Side Effect를 부작용이라고 해석하는 경우가 있다. 여기서 사용하는 '부'자가 우리가 생각하는 부자가 아닐테지만, 부작용이라고 하면 우선 안 좋은 인식부터 든다. 그래서 부차작용이라는 말로 해석해봤다. 하지만 용어는 Side Effect로 사용토록 하겠다.
React 컴포넌트Side Effect라 함은 비동기 요청을 얘기할 수 있다. 컴포넌트를 렌더링 할 때 외부 데이터를 요청해야할 때가 있다. 그리고 이 요청이 어떤 컴포넌트의 State 값에 영향을 미친다면, 그에 따른 업데이트를 해줘야 한다. 이 때 사용하는 것이 useEffect이다.

cf. 참고로 본래 React Component는 마운트 단계까지는 "Pure"한 상태다.


useEffect

예제 1

import React, { useState, useEffect } from 'react';

function Counter(props) {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = count;
    
	const intervalId = setInterval( ()=>setCount(count + 1), 1000)

    return ()=>{clearInterval(intervalId)};
  });
  
  return <div>{count}</div>
}

export default Counter;

간단하게 JavaScript의 대표적인 비동기 함수인 setInterval을 사용하여 State 값 count를 1초마다 1씩 올리는 컴포넌트를 만들어봤다.

cf. useEffect의 사용은 인자로 실행할 콜백 함수를 작성하는 것이다. 필자는 인자에서 바로 명령들을 실행하려다가 큰 오류를 만들고 한참 헤매었다.

useEffect에 실행할 콜백 함수를 작성하여 전해준다. useEffect의 실행은 렌더링 이후에 발생한다. useEffect가 실행되는 조건은 새로운 Props의 유입, 혹은 State 변경 혹은 강제적 Componenet 요소 변경이 있다. 그래서 위에 작성된 useEffect는 count 변수의 변경이 있기 때문에 계속해서 실행된다.

setInterval 함수도 계속해서 실행되는지는 차후에 다시 수정해보겠다. 이 예제에서 useEffect의 역할은 컴포넌트가 Unmount될 때, setInterval을 해제하는 수단으로서의 기능만 담당한다.

예제 2와 종속배열

import React, { useState, useEffect } from 'react';

function Counter(props) {
  const [count, setCount] = useState(0);
  const [isOdd, setIsOdd] = useState(true);
  const [immutable, setImmutable] = useState(null);
  
// 1번째 useEffect
  useEffect(() => {
	const intervalId = setInterval( ()=>setCount(count + 1), 1000)
    return ()=>{clearInterval(intervalId)};
  });
// 2번째 useEffect
  useEffect(()=>{
    setIsOdd(count % 2 === 0 ? false : true)
  }, [count])
  // [immutable] 로 바꿔주면 작동 안 한다.
  
  return (
    <div>
        <p>{count}</p>
        <p>{isOdd ? "홀수" : "짝수"}</p>
    </div>
  )
}

export default Counter;

예제 1에 홀수 짝수 판별하고 엘리먼트의 값으로 반환하는 명령을 추가했다. 이 예제로서 useEffect의 기능을 더 정확히 설명할 수 있겠다. 마찬가지로 count 값은 계속해서 1씩 더해진다. 2번째 useEffect는 인자를 두 개로 받는다. 첫 번째 인자는 실행시킬 콜백함수고, 두 번째 인자는 State 값 중 일부를 담은 배열이 온다. 이를 종속배열이라고 한다.
종속배열에 들어오는 state 값은 그 값이 변경되었는지만 Boolean으로 체크한다. 만약 2번째 useEffect에서 종속배열을 안 써주면 모든 State의 변경에 의해서 실행이 되어버린다. 원하는 State들의 변경에만 useEffect를 실행시켜주고 싶다면 종속배열에 등록해주자.
이렇듯 다른 state 값의 변경에 연동해서 바뀌는 state가 있다면 useEffect를 이용하여 업데이트해주면 컴포넌트는 업데이트 된 부분을 재렌더링 해 줄 것이다.

출처

출처 : 리액트 공식문서
출처 : 코드스테이츠

profile
블록체인 개발 공부 중입니다, 프로그래밍 공부합시다!

0개의 댓글