React 배움의 연속 #9

CoderS·2021년 12월 14일
0

리액트 Remind

목록 보기
9/32

#9 어렵다! 리액트 <- 너

useEffect의 사용방법

이번에는 Hook의 또 다른 기능중에 하나인 useEffect의 대해 알아보겠다.

useEffect는 함수형 컴포넌트에서 효과들을 실행할 때 쓰이며, 기존 클래스 컴포넌트의 라이프사이클 메서드들을 대체한다.

라이프사이클이란?

LifeCycle Method - componentDidMount, componentDidUpdate

메소드는 크게 두 종류로 나눠진다.

  • will 메소드 : 어떠한 작업이 실행되기 직전에 호출
  • did 메소드 : 어떠한 작업이 실행된 직후에 호출

생명주기 메소드에서는 Mount라는 단어가 등장하는데, 여기서 마운트는 리액트가 컴포넌트를 실제 DOM에 삽입하는 것 이다.

여기서 라이프 사이클의 대해 얘기할려면 너무 길어지기 때문에 따로 찾아보는 것을 추천한다!

그리하여 컴포넌트가 마운트 됐을 때 (처음 나타났을 때), 언마운트 됐을 때 (사라질 때), 그리고 업데이트 될 때 (특정 props가 바뀔 때) 특정 작업을 처리하는 방법에 대해 알아보겠다.

우선 UserList의 코드를 수정해준다.

UserList.js

import React, { useEffect } from 'react';

function User({ user, onRemove, onToggle }) {
  useEffect(() => {
    console.log('컴포넌트가 화면에 나타남');
    return () => {
      console.log('컴포넌트가 화면에서 사라짐');
    };
  }, []);
  return (
    <div>
      <b
        style={{
          cursor: 'pointer',
          color: user.active ? 'green' : 'black'
        }}
        onClick={() => onToggle(user.id)}
      >
        {user.username}
      </b>
      &nbsp;
      <span>({user.email})</span>
      <button onClick={() => onRemove(user.id)}>삭제</button>
    </div>
  );
}

function UserList({ users, onRemove, onToggle }) {
  return (
    <div>
      {users.map(user => (
        <User
          user={user}
          key={user.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
}

export default UserList;

useEffect를 사용할 때, 첫 번째 파라미터에는 함수, 두 번째 파라미터에서는 의존값이 들어있는 배열을 넣는다. 만약 두 번째 파라미터를 비우면, 컴포넌트가 처음 등장할때만 useEffect에 등록한 함수가 호출된다.

  1. function : 수행하고자 하는 작업
  2. deps : 배열 형태이며, 검사하고자 하는 특정 값을 넣는다.

그리고 재미있는 사실은 useEffect에서는 함수를 반환 할 수 있는데 이를 cleanup 함수라고 부른다.

cleanup 함수는 useEffect의 뒷정리를 해주는 역할을한다.

두 번째 파라미터 (dependency)가 비어있는 경우에 컴포넌트가 사라질 때 cleanup 함수가 호출된다.

화면을 확인하면...

코드를 작성하고 콘솔을 확인해보니, 새로운 항목을 추가해보고 제거도 해봤다.

컴포넌트가 마운트, 언마운트 될 때 주로 우리가 추가하는 작업

마운트 될 때

  1. props로 받은 값을 컴포넌트의 state로 설정
  2. 컴포넌트가 나타나면 외부 API (REST API)를 요청
  3. 라이브러리를 사용 (D3, Video.js 등)
  4. setInterval이나 setTimeout과 같은 작업 예약

언마운트 될 때

  1. setInterval, setTimeout을 사용해서 등록했던 작업을 제거할 때 즉, clearInterval이나 clearTimeout과 같은 작업
  2. 라이브러리 인스턴스를 만들었다면, 이 인스턴스를 제거

deps 에 특정 값 넣기

이번에는 deps에 특정 값을 넣어보겠다. deps에 특정 값을 넣게 된다면,
컴포넌트가 처음 마운트 될 때 호출되고, 지정한 값이 바뀔 때도 호출이 된다.

그리고, deps 안에 특정 값이 있다면 언마운트시에도 호출이되고, 값이 바뀌기 직전에도 호출된다.

다음과 같이 코드를 수정해보겠다.

UserList.js

import React, { useEffect } from 'react';

function User({ user, onRemove, onToggle }) {
  useEffect(() => {
    console.log('user 값이 설정됨');
    console.log(user);
    return () => {
      console.log('user 가 바뀌기 전..');
      console.log(user);
    };
  }, [user]);
  return (
    <div>
      <b
        style={{
          cursor: 'pointer',
          color: user.active ? 'green' : 'black'
        }}
        onClick={() => onToggle(user.id)}
      >
        {user.username}
      </b>
      &nbsp;
      <span>({user.email})</span>
      <button onClick={() => onRemove(user.id)}>삭제</button>
    </div>
  );
}

function UserList({ users, onRemove, onToggle }) {
  return (
    <div>
      {users.map(user => (
        <User
          user={user}
          key={user.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
}

export default UserList;

새로운 항목을 추가하고 삭제를 해보니 위에처럼 콘솔이 출력되었다.

아 참고로!
useEffect 안에서 사용하는 props, 상태가 있다면, deps에 넣어주어야 한다. 이 것은 규칙이다!

위의 코드에서는 user라는 파라미터가 사용되었기 때문에 배열에 user를 넣어준다.

그리고 만약에 useEffect 안에서 사용하는 props이나 상태를 deps에 넣지 않게 되면은, useEffect 에 등록한 함수가 실행 될 때 최신 props 혹은 상태를 가르키지 않게 된다.

deps 파라미터를 생략하기

deps 파라미터를 생략한다면, 컴포넌트가 리렌더링 될 때마다 호출이된다.

밑에 있는 코드를 이용해서 확인해보자!

UserList.js

import React, { useEffect } from 'react';

function User({ user, onRemove, onToggle }) {
  useEffect(() => {
    console.log(user);
  });
  return (
    <div>
      <b
        style={{
          cursor: 'pointer',
          color: user.active ? 'green' : 'black'
        }}
        onClick={() => onToggle(user.id)}
      >
        {user.username}
      </b>
      &nbsp;
      <span>({user.email})</span>
      <button onClick={() => onRemove(user.id)}>삭제</button>
    </div>
  );
}

function UserList({ users, onRemove, onToggle }) {
  return (
    <div>
      {users.map(user => (
        <User
          user={user}
          key={user.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
}

export default UserList;

아까처럼 똑같이 먼저 등록하고 삭제해봤는데, 모든 항목들이 렌더링될 때마다 다같이 호출된다.

참고 : 벨로퍼트와 함께하는 모던 리액트

느낀점 :

  • 오늘은 Hook의 라이프사이클을 책임지는 useEffect의 대해 알아봤다.
  • 생각보다 이해하는데 시간이 걸렸고 댓글들을 확인하면서 내가 놓친 부분이 있는지 확인해봤다.
profile
하루를 의미있게 살자!

0개의 댓글