JS Library/React

useEffect 를 사용하여 마운트, 언마운트, 업데이트 시 할 작업 선택

원2 2022. 5. 23. 12:00
728x90
반응형

useEffect 가 하는 일?

 

useEffect Hook 을 이용하여 React 에게 컴포넌트가 렌더링 된 이후에 어떤 일을 수행해야하는지를 말하는것

React 는 넘겨준 함수를 기억했다가 (이 함수가 'effect') DOM 업데이트를 수행한 이후에 불러냄

effect 를 통해 데이터를 가져오거나 다른 명령형 (imperactive) API 를 불러내는 일을 할 수도 있음

 

useEffect 를 컴포넌트 안에서 불러내는 이유?

useEffect 를 컴포넌트 내부에 둠으로써 effect 를 통해 const state 변수, prop에 접근할 수 있음

함수 범위 안에 존재하기 때문에 특별한 API 없이도 값을 얻을 수 있음

Hook 은 자바스크립트의 클로저를 이용하여 React 에 한정된 API 를 고안하는 것보다 자바스크립트가 이미 가지고 있는 방법을 이용하여 문제를 해결함

 

useEffect 는 렌더링 이후에 매번 수행

기본적으로 첫번째 렌더링과 이후의 모든 업데이트에서 수행됨

마운팅과 업데이트라는 방식으로 생각하는 대신 effect 를 렌더링 이후에 발생하는 것으로 생각하는 것이 더 쉬울것

또한 React 는 effect 가 수행되는 시점에 이미 DOM 이 업데이트 되었다는 것을 보장

 

  • 마운트 : 처음 나타났을 때
  • 언마운트 : 사라질 때
  • 업데이트 : 특정 props 가 변경 될 때

 


마운트/언마운트

deps 에 값이 없는 경우 배열만 있음.

UserList.js

import React, {useEffect} from "react";

function User({user, onRemove, onToggle}) {

    useEffect(() => {
        console.log("Components appear on the screen");
        return () => {
            console.log("components disappears from screen");
        };
    }, []);

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

// 순서상 UserList 에서 on Toggle 을 받아오고, User 에서 호출
function UserList({users, onRemove, onToggle}) {
    return (
        <div>
            {users.map(user => (
                <User
                    user={user}
                    Key={user.id}
                    onRemove={onRemove}
                    onToggle={onToggle}

                />
            ))}
        </div>
    );
}

export default UserList;

결과

삭제를 누르면 언마운트 되고 등록을 하면 마운트(prop 입력) 언마운트 (input 창의 텍스트가 사라짐) 마운트 (아래에 값이 등록되어 렌더링) 됨.&nbsp; &nbsp; &nbsp;아마도...

 

useEffect 를 사용할 때에는 첫번째 파라미터에는 함수, 두번째 파라미터에는 의존 값이 들어있는 배열(deps) 를 넣음

만약 deps 배열을 비우게 된다면, 컴포넌트가 처음 나타날때에만 useEffect 에 등록된 함수가 호출

 

그리고 useEffect 에서는 함수를 반환 할 수 있는데 이것을 cleanup 함수라고 한다

cleanup 함수는 useEffect 에 대한 뒷정리를 해준다고 생각하면 됨

deps 가 비어있는 경우에는 컴포넌트가 사라질 때 cleanup 함수가 호출

 

 

마운트 시 하는 작업들

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

언마운트 시 하는 작업들

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

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>
            <span>({user.email})</span>
            <button onClick={() => onRemove(user.id)}>삭제</button>
        </div>
    );
}

// 순서상 UserList 에서 on Toggle 을 받아오고, User 에서 호출
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 파라미터를 생략한다면, 컴포넌트가 리렌더링 될 때마다 호출이 된다.

 

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>
            <span>({user.email})</span>
            <button onClick={() => onRemove(user.id)}>삭제</button>
        </div>
    );
}

// 순서상 UserList 에서 on Toggle 을 받아오고, User 에서 호출
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 에 렌더링 하는 리소스를 아낄 수도 있다.ㅇㅇ

 


 

728x90
반응형