티스토리 뷰

▶리액트 useEffect 잘 알고 사용하자...😱

useEffect를 어설프게 알고 사용하다 보니 사용하는 이유라던가 혹은 무한루프를 돌거나 하는 일이 종종 있었는데요..

이번 글을 통해 앞으로는 확실하게 알고 올바르게 사용해 보려고 합니다 😀!

 

🔎 리액트에서 반드시 짚고 넘어가야 하는 개념


아래와 같은 코드가 있다고 해봅시다.

 

export default function Test() {
  const [count, setCount] = useState(0);
  
  const onClickButton = () => {
    count += 1;
    console.log(count);
  }
  
  return(
    <div>
      <div>{count}</div>
      <button onClick={onClickButton}>증가</button>
    </div>
  );
}

리액트에서 위와 같이 코드를 작성하고 증가 버튼을 눌러보면 다음과 같이 되게 되는데요.

증가 버튼 클릭했을 때 화면과 콘솔창

에러를 자세히 보면 TypeError로 count는 constant variable(상수)라고 알려주고 있습니다.

즉 count는 변경하지 못한다고 알려주고 있는데요.

(state를 const로 선언했었습니다)

 

또한 리액트는 한번 렌더링 되어 root 내부에 삽입된 엘리먼트들은 화면을 새로고침 하거나 ReactDOM을 다시 렌더링 하지 않는 이상 업데이트가 되지 않습니다.

 

따라서 내부의 어떤 값을 변경하기 위해서는 우리가 알고 있는 useState라는 훅을 이용해야 하고,

위 코드에서는 useState를 이용해서 count의 state를 변경해줘야 하는데요.

이때 count의 값이 변경되면 리액트는 컴포넌트를 리렌더링 하는 과정을 거치면서 새로운 카운트 값이 표시되게 합니다.

 

🔎 이제 useEffect란 무엇인가 알아보자 


useEffect는 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록 해줍니다.

즉, 위에서 값이 변경되면 컴포넌트가 렌더링 된다고 했었습니다.

 

따라서 useEffect는 컴포넌트가 렌더링 될 때 특정 작업을 실행할 수 있도록 합니다.

 

📌 useEffect가 작동되는 상황들

useEffect는 기본적으로 몇 가지 조건에 의해 작동하게 되는데요.

 

  1. 페이지가 처음 렌더링 되고 난 후 useEffect를 무조건 한번은 실행
  2. useEffect에 배열로 지정한 state의 값이 변경되면 실행

 

즉 useEffect는 렌더링, 혹은 변수의 값 혹은 object가 달라지게 되면, 그것을 인지하고 업데이트를 해주는 함수입니다.

useEffect는 콜백 함수를 부르게 되며 렌더링 혹은 값, object의 변경에 따라

지정한 함수를 동작시킬 수 있게 해줍니다.

 

📌 사용 방법

useEffect를 사용하는 방법은 총 3가지 정도로 정리해 볼 수 있습니다.

// 1.
useEffect(()=>{});

// 2.
useEffect(()=>{}, []);

// 3.
const [count, setCount] = useState(0);
useEffect(()=>{}, [count]);

 

1. useEffect(()=>{})

useEffect의 가장 기본 형태이지만, 이러한 형태를 거의 사용하지는 않습니다.

왜나햐면 의존성 배열(두 번째 인자 자리의 값)이 없기 떄문에

렌더링 할 때 한번, 어떠한 작은 요소라도 변화한다면 시시때때로 useEffect가 발동되어 불필요한 실행이 너무 많아집니다.

 

2. useEffect(()=>{}, [])

useEffect를 렌더링 후 단 한번만 실행하고 싶을 때 사용하는 방법입니다.

두 번째 인자 자리에 아무 변수나 값 없이 대괄호만 있다면,

이 useEffect는 렌더링 후 단 한번만 실행되고 다시는 실행되지 않습니다.

 

3. useEffect(()=>{}, [count])

useEffect를 렌더링 후 한번, 그리고 배열 안 변수의 값이 변할 때마다 실행하는 코드입니다.

이렇게 의존성 배열 안에 값을 지정해주어 지정된 값이 변경했을 때만 실행되게 됩니다.

 

간단한 예시 코드를 통해 좀 더 자세하게 살펴봅시다!

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

const App = () => {
  const [count, setCount] = useState(0); // useState로 number를 0으로 초기화
  const [name, setName] = useState('doeunn');

  useEffect(() => {
    console.log('useEffect call !!!');
  });

  const counter = () => setCount(count + 1);
  const nameChanger = () => setName('jun');

  return (
    <div>
      <div>{count}</div>
      <div>{name}</div>
      <button onClick={counter}>count up</button>
      <button onClick={nameChanger}>change Name</button>
    </div>
  );
};

export default App;

화면

화면은 위와 같이 구성되었고,

알아본 대로라면 useEffect는 화면이 처음 렌더 되었을 때 무조건 한번은 실행된다고 했으므로

콘솔창을 열어보았을 때 'useEffect call !!!'이 출력되어 있어야 하겠죠?

화면과 콘솔창

이제 그러면 버튼을 눌러서 useEffect가 어떻게 실행되는지를 확인해 보겠습니다.

참고로 지금 useEffect 부분의 코드는 아래와 같습니다.

의존성 배열 부분의 인자가 아무것도 없으므로

처음 렌더 되었을 때, 어떤 값이 하나라도 변경되었을 때마다 useEffect의 첫 번째 인자로 작성한 함수가 실행될 것입니다.

// 가장 기본 형태로 작성 되어 있음
useEffect(() => {
   console.log('useEffect call !!!');
});

예상대로라면 처음 렌더 되었을 때랑 버튼을 눌러서 값이 변경될 때마다 useEffect가 실행될 것입니다.

count up 버튼을 두 번 눌렀을 때

count up 버튼을 두 번 눌렀습니다.

그러므로 count의 값이 바뀐 2번 모두 useEffect를 호출한 것을 확인할 수 있었습니다.

 

이번에는 두 번째 경우 useEffect(()=>{}, [])처럼 코드를 작성하여 useEffect를 자세히 살펴보겠습니다.

코드는 위에서 작성한 것과 모두 동일하고

useEffect 부분에서 빈 의존성 배열을 두 번째 인자로 추가해 주었습니다.

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

const App = () => {
  const [count, setCount] = useState(0); // useState로 number를 0으로 초기화
  const [name, setName] = useState('doeunn');

  useEffect(() => {
    console.log('useEffect call !!!');
  }, []);

  const counter = () => setCount(count + 1);
  const nameChanger = () => setName('jun');

  return (
    <div>
      <div>{count}</div>
      <div>{name}</div>
      <button onClick={counter}>count up</button>
      <button onClick={nameChanger}>change Name</button>
    </div>
  );
};

export default App;

처음 렌더되었을 때만 useEffect 호출 !!

빈 의존성 배열을 추가했더니

처음 렌더링 되었을 때만 useEffect를 호출하고

값이 변경되었을 떄는 따로 useEffect가 호출되지 않는 것을 확인할 수 있었습니다.

 

이제 마지막으로 의존성 배열 안에 값을 넣는 경우를 코드로 살펴봅시다.

이번에도 위 코드들과 동일하고 useEffect의 의존성 배열 부분만 수정해 보겠습니다.

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

const App = () => {
  const [count, setCount] = useState(0); // useState로 number를 0으로 초기화
  const [name, setName] = useState('doeunn');

  useEffect(() => {
    console.log('useEffect call !!!');
  }, [name]);

  const counter = () => setCount(count + 1);
  const nameChanger = () => setName('jun');

  return (
    <div>
      <div>{count}</div>
      <div>{name}</div>
      <button onClick={counter}>count up</button>
      <button onClick={nameChanger}>change Name</button>
    </div>
  );
};

export default App;

count를 변경했을 때

저는 의존성 배열안에 name이라는 값을 넣었습니다.

따라서 넣지 않은 count 값이 변경되었을 때는 useEffect를 호출하지 않는 것을 확인할 수 있었습니다.

 

이제 name을 변경해 봅시다.

name 값을 변경했을 때

빈면에 의존성 배열 안에 넣었던 name 값이 변경되었을 때는 useEffect가 호출되는 것을 확인할 수 있었습니다.

 

📌 정리

화면이 처음 렌더링 되었을 때 딱 한번만 특정 함수를 실행하고 싶다

ex. 홈화면에 게시물을 모두 불러오는 경우에는 처음 렌더링 되었을 때만 호출하는게 효율적

→ useEffect( ()=>{}, [ ] )

 

특정 값이 변할 때마다 특정 함수를 실행하고 싶다

→ useEffect( ()=>{}, [ 특정 변수 ] )

 

🔎 useEffect에서 무한루프


📌 무한루프가 발생하는 이유 - 의존성 배열 없이 useEffect안에 setState 해서

흔히 하는 실수 중 하나로....

만약 useEffect 함수 안에 의존성 배열을 명시하지 않고

내부에 useState를 사용 한다면 무한루프가 발생하게 됩니다.

const Example = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setCount(count + 1); // 무한루프 발생
  });

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </div>
  );
};

 

 

📌 해결 방법

단순히 useEffect의 두 번째 인자 자리에 빈 의존성 배열을 넣어주면 됩니다.

왜냐하면 우리가 위에서 알아보았던 것처럼 빈 의존성 배열을 입력해주면

처음 렌더링이 되었을 때 딱 한번만 실행이 되기 떄문이죠!

728x90
LIST
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함