[TIL] useEffect

·2023년 11월 6일
1

TIL

목록 보기
24/85
post-thumbnail

[React에서 rendering이 발생하는 경우]

  • 첫 리액트 앱을 실행했을 때
  • 현재 리액트 내부에 어떤 상태(state)에 변경이 발생했을 때.
    • 컴포넌트 내부 state가 변경되었을 때
    • 컴포넌트에 새로운 props가 들어올 때,

Effect란?

여기서 Effect는 Side Effect와 동일한 의미를 지닌다.
React의 주요한 임무는 UI 렌더링이다. 유저가 키보드를 누르든 클릭을 하든, 입력에 반응하여 필요할 때 UI를 다시 렌더링한다.
Side Effect는 위에서 말한 React의 역할인 UI 렌더링에서 벗어난 모든 것들을 의미한다.

👉 Effect(Side Effect)란, 일반적인 React 컴포넌트 함수 밖에서 일어나는 일들

useEffect()

React 컴포넌트 안에 API 호출하는 부분이 있다면 어떻게 될까?
state가 변경될 때마다 컴포넌트가 rerendering함과 동시에 API호출을 또 하게 될 것이다. 이러면 성능저하는 물론이고, 잘못하면 버그나 무한루프가 발생할 수 있다.
이러한 Side Effect를 처리하기 위한 React Hook이 바로 useEffect() 이다.

useEffect()의 구조

useEffect( 함수, [ 의존성들-dependencies ] )

useEffect()는 두 개의 인수를 받는다.

  1. 함수
  2. 의존성 배열

첫 번째 인수로 주어질 함수 안에는 어떤 SideEffect 코드라도 넣을 수 있다.
이 함수는, 두 번째 인수로 주어질 [의존성 배열] 안에 담긴 값에 변경사항이 생길 경우에만 실행된다.
즉, 이 의존성 배열이 Side Effect가 실행될 타이밍을 알려준다고 할 수 있다.
만약 useEffect()가 포함된 컴포넌트가 rerendering 되더라도 이 함수는 실행되지 않는다. 오로지 [의존성 배열] 안에 담긴 값이 변경될 때만 실행된다.

useEffect( 함수 , [ ] )

만약 위처럼, 두 번째 인수에 [] 빈 배열이 주어진 경우엔, 처음 컴포넌트가 실행된 순간에만 useEffect() 내부의 함수가 실행된다.
그 이후에는 어떤 일이 있어도 함수가 실행되지 않는다.
딱 처음 컴포넌트가 실행될 때만 작동한다.

useEffect()의 Cycle 순서

  1. 컴포넌트가 렌더링됨 (마운트)
  2. useEffect()의 첫 번째로 인수로 넘겨진 함수가 실행됨
    2.1 이때 실행된 함수로 state, props가 변경된 경우, 컴포넌트 재렌더링
  3. 대기 상태에서, useEffect()의 두 번째 인수로 넘긴 의존성 값들에 변경사항이 발생하는 지를 체크
  4. 변경사항이 발생하면 useEffect()의 첫 번째 인수로 넘겨진 함수가 실행됨
    4.1 이때 실행된 함수로 state, props가 변경된 경우, 컴포넌트 재렌더링
  5. 컴포넌트가 사라지면 같이 사라짐 (언마운트)

예시

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

function App() {
  const [counter, setCounter] = useState(0);
  const handleClick = () => setCounter((prev) => prev + 1);
  console.log("i run all the time");
  const iRunOnlyOnce = () => {
    console.log("i run only once");
  };
  useEffect(iRunOnlyOnce, []);
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={handleClick}>Click Me!</button>
    </div>
  );
}

export default App;

위 코드를 실행하면 i run all the time은 state가 변경될 때마다 실행되고
i run only once 는 한 번만 실행된다. (처음 실행될 때)
여기서 useEffect() 는 우리 코드가 딱 한번만 실행될 수 있도록 보호해준다.

import { useState, useEffect } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => setKeyword(event.target.value);

  useEffect(() => {
    console.log("I run only once");
  }, []); // 빈 배열일 때는 한 번만 실행된다. (ex API 호출)
  useEffect(() => {
    console.log("I run when 'keyword' changes.");
  }, [keyword]); // keyword값이 update 될 때 실행된다 (맨 처음 포함)
  useEffect(() => {
    console.log("I run when 'counter' changes.");
  }, [counter]); // counter값이 update 될 때 실행된다 (맨 처음 포함)
  useEffect(() => {
    console.log("I run when keyword or counter changes.");
  }, [keyword, counter]); // keyword값 또는 counter값이 update 될 때만 실행된다 (맨 처음 포함)
  return (
    <div>
      <input
        value={keyword}
        onChange={onChange}
        type="text"
        placeholder="Search Here..."
      />
      <h1>{counter}</h1>
      <button onClick={onClick}>welcome</button>
    </div>
  );
}

export default App;

useEffect(() => {}, [keyword]); : keyword 값이 변화할 때마다 첫 번째 매개변수 함수가 실행된다.
useEffect(() => {}, [counter]); : counter 값이 변화할 때마다 첫 번째 매개변수 함수가 실행된다.
useEffect(() => {}, [keyword, counter]); : keyword 또는 counter 값이 변화할 때마다 첫 번째 매개변수 함수가 실행된다.


참고: https://arnopark.tistory.com/770

CleanUp

useEffect(() => {
  // 🔴 Avoid: Cleanup logic without corresponding setup logic
  return () => {
    doSomething();
  };
}, []);

컴포넌트가 나타났을 때 (렌더링 됐을 때) useEffect의 effect 함수가 실행되고,
컴포넌트가 사라졌을 때 클린 업 (clean up) 부분이 실행된다.
클린 업은 useEffect 안에서 return 부분에 실행되길 원하는 함수를 넣으면 된다.

// App.jsx

import React, { useEffect } from "react";

const App = () => {

	useEffect(()=>{
	 // 화면에 컴포넌트가 나타났을(mount) 때 실행하고자 하는 함수를 넣어주세요.

		return ()=>{
	 // 화면에서 컴포넌트가 사라졌을(unmount) 때 실행하고자 하는 함수를 넣어주세요.
		}
	}, [])

	return <div>hello react!</div>
};

export default App;

예시

create 될 때 뿐만아니라 destroy 될 때도 무언가 동작하게 하고 싶다면 cleanUp을 활용하자.

import { useState, useEffect } from "react";

function Hello() {
  useEffect(() => {
    console.log("created :)");
    return () => console.log("destroyed :("); // cleanUp 함수
  }, []);
  return <h1>Hello</h1>;
}

function App() {
  const [showing, setShowing] = useState(false);
  const onClick = () => setShowing((prev) => !prev);
  return (
    <div>
      {showing ? <Hello /> : null}
      <button onClick={onClick}>{showing ? "Hide" : "Show"}</button>
    </div>
  );
}

export default App;

Show 버튼 클릭 시 Hide 버튼으로 바뀌고 Hello 라는 문자가 나타난다.
Hide 버튼 클릭 시 Show 버튼으로 바뀌고 Hello 라는 문자가 사라진다.

profile
느리더라도 조금씩, 꾸준히

0개의 댓글