[React] Effect Hook

6046 단어 TILReactReact

Side Effect와 Pure Function

Side Effect
함수 내에서의 어떤 구현이 함수 외부에 영향을 끼치는 경우, 해당 함수는 Side Effect(부수 효과)가 있다고 표현한다.

Pure Function
Pure Function(순수 함수)는 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미한다. 또한 순수 함수는 외부에 영양을 주지도, 받지도 않기 때문에 Side Effect가 없다. 외부에 끼친 영향이 함수의 결과에 영향을 줄 수도 있기 때문이다. 순수 함수는 call by reference로 매개변수에 전달된 입력값을 수정하지 않으며, 특정 전달인자에 대해 항상 동일한 값이 리턴됨을 보장한다. 따라서 순수 함수는 예측 가능한 함수이다.

예를 들어 Math.random() 함수는 결과를 예측할 수 없으므로 순수 함수가 아니다. 또한 fetch API를 이용해서 AJAX 요청을 하는 함수도 순수 함수가 아니다. 네트워크 요청은 서버 데이터에 Side Effect를 일으킬 수 있고, 클라이언트나 서버에서 처리 과정 중에 에러가 발생할 수도 있으므로 결과를 예측할 수 없다.

React의 함수 컴포넌트

앞서 작성한 React의 함수 컴포넌트는 props가 입력으로 들어와 JSX Element를 출력한다. 어떤 Side Effect도 없고, 순수 함수로 작동한다.

function SingleMessage({ children }) {
  return (
    <li className="message">
      <div>{children}</div>
    </li>
  );
}

React 컴포넌트에서의 Side Effect

  • 타이머 사용(setTimeout)
  • 데이터 가져오기(fetch API, localStorage)

하지만 보통 React 애플리케이션을 만들 때는 AJAX 요청이나 localStorage, 타이머와 같이 React와 상관없는 API를 사용하는 경우가 생길 수 있다. 이는 React 입장에서는 전부 Side Effect이며 React는 Side Effect를 다루기 위한 Effect Hook을 제공한다.

Effect Hook: useEffect

Hook 규칙
Hook은 class를 작성하지 않고도 state와 다른 React 기능들을 사용할 수 있게 해준다. Hook은 반드시 React 함수 내 최상위(the top of level)에서만 호출해야 한다. 반복문, 조건문, 혹은 중첩된 함수 내에서 Hook을 호출하면 안 된다. 이 규칙을 지켜야 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출되는 것을 보장한다.

useEffect
useEffect는 함수 컴포넌트 안에서 Side Effect를 실행할 수 있게 하는 Hook이다.

useEffect(함수, 종속성 배열?)

useEffect의 첫 번째 인자는 함수이고, 이 콜백 함수를 effect라 부른다. 해당 함수 내부에서 Side Effect를 실행하면 된다. useEffect는 새롭게 컴포넌트가 렌더링 된 이후, 즉 DOM이 업데이트 된 이후에 effect를 실행한다. 구체적으로는 다음 3가지 경우에 호출된다.

  • 컴포넌트 생성 후 처음 화면에 렌더링 된 이후
  • 컴포넌트에 새로운 props가 전달되어 렌더링 된 이후
  • 상태가 변경되어 컴포넌트가 렌더링 된 이후

useEffect의 두 번째 인자는 종속성 배열(dependency array)로 effect 함수의 실행 조건을 나타낸다. 생략할 경우 effect는 위의 3가지 경우에 전부 호출된다. 종속성 배열을 지정하면 컴포넌트가 처음 화면에 렌더링 된 이후에는, 해당 배열 내의 값이 변할 때만 effect가 실행된다. 보통 기준이 될 상태(state)를 대괄호로 감싸서 배열로 만들고 인자로 전달한다.

useEffect(함수, [state])

빈 배열을 인자로 전달하면 컴포넌트가 처음 생성되고 렌더링 된 이후, 단 한번만 effect 함수가 실행된다. 대표적으로 외부 API를 통해 리소스를 받아온 뒤 더이상 API 호출이 필요하지 않은 경우 사용할 수 있다.

useEffect(함수, [])

다음은 useEffect를 사용해 fetch API로 서버에서 리소스를 요청하는 예시이다. 입력값에 따라 종속성 배열에 할당된 filter 상태가 변경될 때마다 fetch가 호출되며, 필터링 된 결과를 서버에서 받아온다.

useEffect(() => {
  fetch(`서버 주소?q=${filter}`)
    .then(resp => resp.json())
    .then(result => {
      ...
    });
}, [filter]);

좋은 웹페이지 즐겨찾기