React Hook - useEffect

YEONGHUN KO·2022년 2월 18일
0

REACT JS - BASIC

목록 보기
12/30
post-thumbnail

useEffect를 이용해 componentDidMount를 구현해보자

  • Hook중에 useEffect라는 함수가 있다. 이는 함수컴포넌트가 랜더링될때마다 실행되는 함수로 클래스 컴포넌트의 componentDidMount와 유사하다.(랜더링 될때마다 실행되므로 함수컴포넌트 최초 실행시에도 실행된다.)

그럼 간단하게 useEffect를 통해서 movie api를 호출한다음 title을 랜더링 해보도록 하자.

import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';

function SWMovies() {
  const [number, setNumber] = useState(1);
  const [movie, setMovie] = useState('');

  useEffect(() => {
    async function getData() {
      const response = await axios.get(
        `https://swapi.dev/api/films/${number}/`
      );
      setMovie(response.data);
    }
    getData();
  });

  return (
    <div>
      <h1>Pick A Movie</h1>
      <h4>{movie.title}</h4>
      <select value={number} onChange={e => setNumber(e.target.value)}>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
        <option value="6">6</option>
        <option value="7">7</option>
      </select>
    </div>
  );
}
export default SWMovies;

dropdown을 select로 구현한다음 숫자를 선택하면 그에 해당되는 스타워즈 영화의 제목이 나오도록 했다. 참고로, useEffect를 사용할때는 무언가 리턴이 되는 함수를 사용하면 안된다. 따라서 arrow 함수안에 또다시 함수를 만들어서 사용했다.

그러나 요렇게 코드짜면, 문제가 생겨버린다. 어떤 문제일까??...

바로 그 유명한 stackOverFlow가 생긴다ㅋㅋ.

setNumber가 실행되면서 랜더링되고 useEffect가 실행되면서 setMovie가 실행된다. 그럼 랜더링되면서 useEffect가 실행되면서 무한 반복이다. 따라서 number가 바뀔때만 useEffect가 한 번만 실행되도록 해야한다. 이때 useEffect의 2번째 인자에 number를 넣으면 된다.

useEffect(() => {
    async function getData() {
     blah
     blah
  }, [number]);

두번째 인자 array 안에 들어가는 값이 변하면 useEffect가 실행된다. 이렇게 useState와 연계해서 사용가능하다.

그러나, 만일 useState의 초기값에 아무것도 pass되지 않는다면, axio에서 오류가 날것이다. 이런 경우를 대비해서 초기값을 설정해주자.

또는, useRef Hook 함수를 사용하여 에러를 방지 할 수 도 있다.

const isFirstRun = useRef(true);
useEffect(() => {
  async function getData() {
    if (isFirstRun.current) {
      isFirstRun.current = false;
      return;
    }
    const response = await axios.get(`https://swapi.dev/api/films/${number}/`);
    setMovie(response.data);
  }
  getData();
}, [number]);

참고로 effect 라는 이름을 잘 생각해보자. 효과이다. 컴포넌트가 랜더링되고 난 뒤에 실행되므로 어떤 효과를 줄 수 있는 것이다. 즉, 부수효과 sideEffect를 야기할때도 useEffect를 쓴다. 데이터를 불러온다거나 이벤트를 등록할때와 같이 리액트 함수와 관련없는 일을 하고 싶을때는 useEffect안에서 실행하면 된다.

그리고 이벤트같은거 등록해주고 난뒤에는 return을 이용해서 remove해주자.

참고자료:
useRef
useEffect

profile
'과연 이게 최선일까?' 끊임없이 생각하기

0개의 댓글