[React] useEffect

Joah·2022년 6월 13일
0

React

목록 보기
15/31
post-thumbnail

useEffect 왜 필요한가?

useEffect를 배우기 전 state, props, event 세 가지 개념을 활용해 워하는 UI화면 을 렌더링 하는 방법을 배웠다.
하지만 웹 사이트를 구현하기 위해 이 세 가지 개념으로는 조금 부족하다.

예를 들어,

화면에 보일 수 있는 데이터를 서버에서 받아오기,
state가 바뀔 때마다 함수를 실행 시키거나
이벤트 리스너를 달았다가 해제하는 등의 동작이 필요할 수 있다.

useEffect는 이럴 때 필요하다.


예시

import React, {useState} from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);
  console.log("rendering");
  
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={()=>setCount(count + 1)}></button>
    </div>
  );
}

export default Counter;
  • 버튼을 클릭하면 <h1>태그 안에 있는 Count: 0이 1씩 증가한다.

  • 이 때 콘솔을 확인하면 "rendering"이라는 문자열이 2번 찍혀있는 것을 볼 수 있다.

    • 최초에 랜더링 될 때 한 번(마운트)
    • onClick이 발생하여 다시 Counter component를 re-rendering하면서 두 번 출력됨
  • 위의 코드에서 console.log는 저번 블로그에 작성했던 Side Effect를 초래한다.

  • 함수 안에 Side Effect를 발생시키는 코드를 작성하면 2가지 문제점이 있다.



Side Effect의 2가지 문제점(useEffect 탄생비화)

1. Rendering Blocking

  • 자바스크립트에서 코드는 위에서 아래로 읽힌다.
  • 최초에 한 번 랜더링 되고
  • 그 후에는 버튼을 누르면 다시 랜더링 된다.
  • 랜더링을 하게 되면 Counter 컴포넌트를 처음부터 다시 시작한다.
  • 따라서 doSomeSideEffect() 가 실행되고 console.log("rendering")이 실행된다.
import React, { useState } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);
  
  doSomeSideEffect();
  console.log("rendering");
  
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>increase</button>
    </div>
  );
};

function doSomeSideEffect() {
  console.log("side effect strat");
  console.log("side effect end");
}

export default Counter;
  • 만약 JSX가 작성된 return 문 전에 `doSomeSideEffect 함수에 5초 이상 걸리는 Side Effect가 있다면?

    • 엄청 긴 for문을 돌리거나
    • 큰 용량의 데이터를 가져오거나
  • 위에서부터 읽히기 때문에 해당 함수가 끝나기 전까지는 rendering이 되지 않아 return문에 작성된 JSX를 그려내지 못한다. 따라서 5초 이상 UI상에 아무런 그림이 그려지지 않는다.

  • 이후에 버튼을 다시 눌렀을 때, 또 다시 5초 이상을 기다려야 한다. rendering을 다시하기 때문이다.

    만약 웹 사이트가 처음에 로드되는데 5초 이상 걸린다. 사용자가 그래도 기다렸다. 그 다음 버튼 하나를 눌렀는데 또 5초 이상 기다린다. 그 사이트 도대체 누가 사용할까?

💥따라서 Side Effect는 rendering을 막으면 안된다!

🔑그럼 어떻게 해야할까???

rendering을 하고 Side Effect를 수행하는 건 어떨까?

그럼 side effect가 10초가 걸리든 일단 화면은 나타나고 다음의 일이니깐 그 시간 후에 업데이트만 되면 되니깐 이게 어떨까?

와... 직접 구현하기 빡시네...

React Team: 님들 내가 직접 만들어드림 밑에 코드로 import 하심 됨

import {useEffect} from 'react';

너를 살려주려 왔다 useEffect

useEffect(()=>{},[])
  • useEffect는 함수이다.
  • 첫 번째 매개변수는 callback 함수
    • side effect로 진행해야 하는 함수를 인자로 넘겨준다.
import React, { useState, useEffect } from "react";

const Counter = () => {
  const [count, setCount] = useState(0);
  
  useEffect(doSomeSideEffect);
  console.log("rendering");
  
  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>increase</button>
    </div>
  );
};

function doSomeSideEffect() {
  console.log("side effect strat");
  console.log("side effect end");
}

export default Counter;

  • useEffect의 callback함수로 doSomeSideEffect()를 부여했더니
    - 위에서 아래로 읽는 자바스크립트이지만 useEffect는 "랜더링 안막을게! 일단 랜더링부터 해!"
    - 분명 useEffect를 먼저 호출했는데 왜? console.log("rendering")을 먼저 실행?
    - useEffect를 사용하면 랜더링을 먼저 실행하고 난 다음에 useEffect의 callback함수를 실행한다.

    여러개의 useEffect 가 있다면?
    사용 횟수에 제한은 없다.
    useEffect가 여러 개 있다면 그들끼리는 순서가 있다.
    차곡차곡 외부 저장소에 기억해두고 랜더링이 끝나고 하나하나 실행한다.
    따라서 순서가 보장된다.


2. Side Effect가 매 랜더링마다 실행

(아직 side effect 의 문제점을 작성 중이다.)

그래, rendering 후에 Side Effect가 실행되는 건 좋아. 근데 버튼을 누를 때마다 실행되며 매번 랜더링하잖아... 어쩔때는 매번..? 필요없어!!

  • 우리가 입력할때만, 필요할때만 호출하고 싶다면? 매 랜더링마다 실행되는 것 말고,
  • 처음 한 번만 또는 어떤 값이 변했을 때만 side effect를 실행하고 싶을 때!

dependency array 의존성 배열(useEffect의 두 번째 매개변수)
Side Effect의 실행 여부를 결정짓는다. 실행 타이밍, Side Effec 실행 해? 말어?를 배열 안의 요소에 따라 결정하는 것

  • 만약 배열 안의 데이터를 작성했는데 작성한 데이터가 rendering 전과 후의 값이 변경되었다면 Side Effect를 실행해라
useEffect(doSomeSideEffect); //배열이 없다면 매 랜더링마다 실행하라
useEffect(doSomeSideEffect, [count]);//count가 변했을 때만 side effect를 실행하라
useEffect(doSomeSideEffect, [count, inputValue]); //둘 중 하나라도 변했을 때 side effect를 실행하라
useEffect(doSomeSideEffect,[]);
//초기 랜더링 처음에만 실행한다. 이거 바뀌면 실행해 인데 이거가 없음 그럼 처음에 랜더링 할 때만 실행한다.
// 첫 랜더링 때만 필요한 데이터 가져올 때 사용
profile
Front-end Developer

0개의 댓글