[TIL-20210629] useEffect / Hook

Pizzahand·2021년 6월 30일
0

TIL

목록 보기
21/28
post-thumbnail
post-custom-banner

Side Effect(부수 효과)

함수 내에서 어떤 구현이 함수 외부에 영향을 끼치는 경우 해당 함수는 Side Effect가 있다고 이야기 한다.

// side effect 예제
let foo = 'hello'; // 전역변수  --  함수 외부

function bar() {
  foo = 'world'; // 함수 내의 어떤 구현
}

bar(); // bar는 Side Effect를 발생!

Pure Function (순수 함수)

순수 함수란, 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 말한다. 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 경우, 순수 함수라고 부를 수 없다. 또한 순수 함수는, 입력으로 전달된 값을 수정하지 않는다. 순수 함수에는 네트워크 요청과 같은 Side Effect가 없다. 순수 함수의 특징 중 하나는, 어떠한 전달 인자가 주어질 경우, 항상 똑같은 값이 반환됨을 보장한다. 그래서 예측 가능한 함수이기도 하다.

function upper(str) {
  return str.toUpperCase(); // toUpperCase 메소드는 원본을 수정하지 않습니다 (Immutable)
}

upper('hello') // 'HELLO'  --  str = 'hello'

React의 함수 컴포넌트

React의 함수 컴포넌트는, props가 입력으로, JSX Element가 출력으로 나간다. 그 어떤 Side Effect도 없으며, 순수 함수로 작동한다.

function SingleTweet({ writer, body, createdAt }) {
  return <div>
    <div>{writer}</div>
    <div>{createdAt}</div>
    <div>{body}</div>
  </div>
}

하지만 보통 React 애플리케이션을 작성할 때에는, AJAX 요청이 필요하거나, LocalStorage 또는 타이머와 같은 React와 상관없는 API를 사용하는 경우가 발생할 수 있다. 이는 React의 입장에서는 전부 Side Effect 이다. React는 Side Effect를 다루기 위한 Hook인 Effect Hook을 제공한다.

React 컴포넌트에서의 Side Effect 예시

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

Hook

Hook의 규칙

  • 최상위(at the Top Level)에서만 Hook을 호출해야 합니다.
    반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하지 마세요. 대신 early return이 실행되기 전에 항상 React 함수의 최상위(at the top level)에서 Hook을 호출해야 합니다. 이 규칙을 따르면 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장됩니다. 이러한 점은 React가 useState 와 useEffect 가 여러 번 호출되는 중에도 Hook의 상태를 올바르게 유지할 수 있도록 해줍니다.
  • 오직 React 함수 내에서 Hook을 호출해야 합니다
    Hook을 일반적인 JavaScript 함수에서 호출하지 마세요. 대신 아래와 같이 호출할 수 있습니다.
    • React 함수 컴포넌트에서 Hook을 호출하세요.
    • Custom Hook에서 Hook을 호출하세요.

이 규칙을 주의해서 지키면 컴포넌트의 모든 상태 관련 로직을 소스코드에서 명확하게 보이도록 할 수 있습니다.

useEffect

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

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

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

  useEffect(() => {  // 버튼을 클릭할 때 마다 useEffect를 통해 title을 변경하게 된다.
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

위 예제를 보면 화면에 button이 있고, 클릭하게되면 할 때 마다 useEffect를 통해서 title이 변하게 된다.
useEffect의 첫번째 인자는 함수이다. 해당 함수 내에서 side effect를 실행하면 된다. 이 함수는 다음과 같은 조건에서 실행된다.

  • 컴포넌트 생성 후 처음 화면에 렌더링(표시)
  • 컴포넌트에 새로운 props가 전달되며 렌더링
  • 컴포넌트에 상태(state)가 바뀌며 렌더링

이렇게 매 번 새롭게 컴포넌트가 렌더링될 때 Effect Hook이 실행된다.

profile
재밌게 코딩하고 싶은 개발자!
post-custom-banner

2개의 댓글

comment-user-thumbnail
2021년 7월 1일

잘 보고갑니다.. 갑자기 남은 엽떡 다시 먹고싶다....

1개의 답글