[React] useEffect(콜백 함수, 배열)

MINEW·2022년 11월 3일
0

함수 컴포넌트에서 Lifecycle

  • useEffect는 함수 컴포넌트에서 라이프사이클로 사용합니다.
  • useEffect에 첫번째 인자로 콜백 함수를 넣고 두번째 인자로 배열을 넣는데, 빈 배열을 넣으면 컴포넌트가 최초 렌더링 됐을때 1번만 실행됩니다.
  • 배열에 변수명을 넣으면, 변수명에 넣은 값이 업데이트 될 때마다 실행됩니다. 단, 처음 렌더링될때는 자동실행되기 때문에, 처음 렌더링될때 자동실행되지 않기를 원하면 따로 if로 처리 해줘야 합니다.
  • 콜백 함수에 return값으로 또 다른 콜백 함수를 넣으면, 컴포넌트가 제거될 때 호출하는 용도로 사용됩니다. (새로 렌더링하기전에 정리하는 용도)

기본 설명

import { useEffect } from 'react' // 필수

// componentDidMount(): 컴포넌트가 처음 렌더링 됐을때, 1번만 실행. (리렌더링 될때는 실행안된다)
useEffect(콜백함수, []);

// componentDidUpdate(): 변수명에 넣은 값이 업데이트 될 때마다, 실행. (단, 처음 렌더링될때는 자동실행된다)
useEffect(콜백함수, [변수명]);

// 참고) 만약, 처음 렌더링될때 자동으로 실행되지 않고, 변수가 업데이트 되었을때만 실행되게 하고 싶다면?
const mounted = useRef(false); // useRef 용도 2

useEffect(() => {
  if (!mounted.current) { // 처음 렌더링될때는 실행하지말고
    mounted.current = true // useRef의 값을 조회, 수정 할 때는 .current를 이용해야한다.
  } else { // 업데이트 될때만 실행해줘
    // 함수 내용 작성
  }
}, [변수명]);

기본 예시

// <!-- FunctionClock.js -->
import React, { useState, useEffect } from 'react';

function FunctionClock(props) {
  const [ date, setDate ] = useState(new Date());

  function tick() {
    setDate(new Date());
  };

  // 컴포넌트가 처음 렌더링 됐을때, 1번만 실행 (1시42분49초에 페이지에 들어가면, 1시42분49초에 호출)
  useEffect(() => {
    console.log("componentDidMount");
    const timerID = setInterval(tick, 1000); // 자동 실행
    
    // 컴포넌트가 제거될 때 호출 (새로 렌더링하기전에 정리하는 용도)
    return () => { console.log("componentWillUnmount"); clearInterval(timerID); };
  }, []);

  // 변수명에 넣은 값이 업데이트 될 때마다, 실행 (1시42분49초에 페이지에 들어가면, 1시42분49초에 호출 + 업데이트 될때마다 호출)
  useEffect(() => {
    console.log("componentDidUpdate");
    console.log(date);
  }, [date]); // 렌더링과 관련된 값이어야 한다 & 객체값을 넣는 것은 지양된다

  return (
    <div>
      <h1>{ date.toLocaleTimeString() }</h1>      
    </div>
  );
}

export default FunctionClock;

나쁜 예시 vs 좋은 예시

// BAD
useEffect(() => {
  fetchIssues();
}, [fetchIssues])

// GOOD
useEffect(fetchIssues, [fetchIssues])

useEffect 의존성 배열

  1. useEffect는 배열에 useRef를 넣을 경우, 변화를 감지하지 못한다
import { useEffect, useRef, useState } from "react";

function App() {
  const count  = useRef(0);
  const countBtn = () => count.current = count.current + 1;

  const [value, setValue] = useState(0);
  const valueBtn = () => setValue((prev) => prev + 1); // 3번) useState 등으로 리렌더링을 발생켜야 -> ref 값도 리렌더링 되면서

  useEffect(() => { // 2번) 콜백함수가 작동하지 않는다! // 5번) 콜백함수를 실행시킨다.
    console.log(count);
  }, [count.current]); // 1번) 배열에 useRef가 들어올 경우, ref가 변경되었는지 감지하지 못하기 때문에 // 4번) 변화를 감지하고

  useEffect(() => {
    console.log(count);
    console.log(value);
  }, [value === 5]); // 참고) 배열에 특정조건을 넣어도 동작한다. 다만, 최초 렌더링 시에 실행 1번 + 해당 조건일 때 실행 1번 + 그 다음번에 1번 더 실행된다.


  return (
    <div>
      <div>{ count.current }</div>
      <button type="button" onClick={countBtn}>Count 버튼</button>

      <div>{ value }</div>
      <button type="button" onClick={valueBtn}>Value 버튼</button>
    </div>
  );
}

export default App;

profile
JS, TS, React, Vue, Node.js, Express, SQL 공부한 내용을 기록하는 장소입니다

0개의 댓글