(React) useEffect 마운트 / 마운트 / 업데이트 시 할 작업 설정하기

호두파파·2021년 4월 6일
0

React

목록 보기
3/38

본 글은 벨로퍼트의 모던 자바스크립트를 바탕으로 작성되었습니다.
본문보기


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

마운트 / 언마운트

userlist.js

function User({ user, onRemove, onToggle }) {
	useEffect(() => {
      consol.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를 사용 할 때에는 첫번째 파라미터에는 함수, 두번째 파라미터에는 의존값이 들어있는 배열 (deps)을 넣습니다. 만약에 deps 배열을 비우게 된다면, 컴포넌트가 처음 나타날때에만 useEffect에 등록한 함수가 호출됩니다.

그리고, useEffect에서는 함수를 반환할 수 있는데 이를cleanup함수라고 부른다. cleanup함수는 useEffect에 대한 뒷정리를 해준다고 이해하면 편하다. deps가 비어있는 경우에는 컴포넌트가 사라질때 cleanup가 호출된다.

주로 마운트 시에 하는 작업들은 다음과 같은 사항들이 있다.

  • props로 받은 값을 컴포넌트의 로컬 상태로 설정
  • 외부 API요청(REST API 등)
  • 라이브러리 사용(D3, Video.js 등...)
  • setInterval을 통한 반복잡업 혹은 setTimeout을 통한 작업 예약

그리고 언마운트 시에 하는 작업들은 다음과 같은 사항들이 있다.

  • setInterval, setTimeout을 사용하여 등록한 작업들 clear 하기
  • 라이브러리 인스턴스 제거

deps에 특정 값 넣기

deps에 특정값을 넣게 된다면, 컴포넌트가 처음 마운트 될 때에도 호출이 되고, 지정한 값이 바뀔 때에도 호출이 된다. 그리고, deps 안에 특정 값이 있다면 언마운트시(맨처음)에도 호출이 되고, 값이 바뀌기 직전에도 호출이 된다.

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가 있다면, useEffect의 deps에 넣어주어야 한다. 그렇게 하는 것이 규칙이다.

만약 useEffect안에서 사용하는 상태나 props를 deps에 넣지 않게 된다면 useEffect에 등록한 함수가 실행될 때 최신 Props/상태를 가리키지 않게 된다.

최신 상태를 계속 갱신하며 주시해야 하는 경우 값을 반드시 넣어주자!

deps 파라미터를 생략하기

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

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;

참고로 리액트 컴포넌트는 기본적으로 부모컴포넌트가 리렌더링되면 자식 컴포넌트 또한 리렌더링이 된다. 바뀐 내용이 없다 할지라도 말이다.

물론, 실제 DOM에 변화가 반영되는 것은 바뀐 내용이 있는 컴포넌트에만 해당한다. 하지만, Virtual DOM에는 모든걸 다 렌더링하고 있다.

나중에는, 컴포넌트를 최적화 하는 과정에서 기존의 내용을 그대로 사용하면서 Virtual DOM에 렌더링하는 리소스를 아낄 수 있다.

useEffect를 사용할때, 값이 변하는 것을 확인하려면 deps파라미터에 값을 반드시 넣어주자!

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글