Skip to content

Instantly share code, notes, and snippets.

@ninanung
Last active November 14, 2022 17:30
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ninanung/0ea87bc3d14ed8b1f9e7488561a4b910 to your computer and use it in GitHub Desktop.
Save ninanung/0ea87bc3d14ed8b1f9e7488561a4b910 to your computer and use it in GitHub Desktop.
때늦은 React Hooks 시리즈 2탄 - useEffect

이 글의 코드는 저자의 Github에서 확인할 수 있습니다.

때늦은 React Hooks 시리즈 2탄 - useEffect

useEffect

지난글에서 useState를 이미 살펴 보았습니다. 간단히 정리하자면 "함수형 컴포넌트에서도 state를 사용할 수 있다! 개꿀!" 이었죠? 하지만 사용만 한다고 다가 아닌것이 우리내 코딩 인생이고, 복잡한 로직을 위한 다양한 기능들을 살펴볼 필요가 당연히 있습니다. useEffect는 그러한 기능들 중 하나로 useState가 기존의 방식을 대체하는 것 처럼 해당 기능 역시 componentDidUpdatecomponentDidMount를 대신한다고 봐도 좋을 것 같습니다. 정확한 기능을 먼저 말해보자면, 리엑트 컴포넌트가 렌더링될때 자동으로 해당 함수를 호출하게 되는데, 지난글에서 설명한 Hook을 이를 통해 이해할 수 있을 것 같네요. 특정 동작이 발생하면 특정 행동을 자동으로 실행한다. 네, Hook입니다.

const UseEffectExample = () => {
  const [test, setTest] = useState('initial value');
  useEffect(() => {
    console.log('렌더링!');
  });

  return (
    <div>
      <p>{test}</p>
      <input onChange={(e) => {setTest(e.target.value)}} />
    </div>
  )
}

위의 코드를 봅시다. 지난 글의 코드에서 크게 바뀐건 없고, 아주아주 간단한 useEffect를 추가했을 뿐입니다. 해당 컴포넌트가 렌더링 될 때마다 useEffect함수가 실행되면서 콘솔에 로그를 남깁니다. 바로 이렇게 말이죠!

useeffect1

기존의 state처럼, state의 값이 변경될 경우 렌더링을 새로 시도하기 때문에, input에 타자를 칠때마다 로그가 찍히게 됩니다.

state 특정하기

흠, 그런데 만약 state가 여러개이고 useEffect함수가 그 state들이 변경될 때 마다 호출된다면 어떨까요? 딱 들어봐도 비효율 적일 것 같은 느낌이 나지 않나요? 이런 상황을 위해서 useEffect는 두번째 매개변수 인자를 받을 수 있습니다.

useEffect(() => {
  console.log('렌더링!');
},[test]);

위의 코드와 같이 배열 형태로 특정 state를 넘기게 되면, 해당 state의 값이 변경될 때만 useEffect함수가 호출되게 됩니다. 흠, 그런데 만약 여러개의 state에 대해서 여러개의 개별적인 동작을 실행시키고 싶다면 어떨까요?

useEffect(() => {
  console.log('test state에 대해서만 호출!')
}, [test])

useEffect(() => {
  console.log('test2 state에 대해서만 호출!')
}, [test2])

간단합니다. 여러개의 useEffect를 설정하면 됩니다. 간단하죠? 실제 동작을 살펴보면 아래와 같이 실행됩니다.

useeffect2

첫 렌더링에만 호출하기

흠, 그런데 만약 렌더링 될 때마다 호출되는 것이 아니라 처음에 렌더링 될 때 한번만 실행하고 싶은 경우에는 어떨까요? 이 역시 방법이 있습니다. 매개변수를 넘기되, 빈 배열로 넘기는 겁니다. 바로 이렇게요.

useEffect(() => {
  console.log('첫 렌더링에만 호출')
}, [])

이렇게 할 경우 처음 렌더링 되는 한번만 호출되고, 이후의 어떠한 렌더링에도 재호출 되지 않습니다. 이렇게요.

useeffect3

자 여기까지 해서 useEffect에 대해서 알아 보았습니다.

컴포넌트가 unmount될때 호출하기

컴포넌트가 렌더링 될 때마다 useEffect함수를 호출하는건 이제 모두 알았을 것 같습니다. 그럼 컴포넌트가 unmount될때는 어떻게 해야 할까요? 사실 그런 경우에도 같은 구문을 사용하면 되지만 약간 변경해서 useEffect함수에서 return을 해주면 됩니다.

useEffect(() => {
  console.log('state가 변경될 때 마다 호출!');
  return () => {
    console.log('언마운트 시 호출!')
  }
})

원래 없던 return이 추가됐습니다. 역시나 간단하게 콘솔에서 로그를 찍을뿐입니다. 해당 결과를 쉽게 예상이 되겠죠?

useeffect4

위의 이미지를 보면 state가 변경될 때 마다 기존의 컴포넌트가 unmount되면서 로그를 찍고 다시 렌더링 되면서 로그를 찍습니다. 눈치가 빠른 분들이면 이미 눈치 챘겠지만, 두번째 인자에 state를 줬을 경우에는 해당 state의 변화에 대한 unmount에만 반응하게 됩니다. 이 경우의 코드는 이미 너무 자명하기 때문에 생략합니다.

마지막 unmount에서만 호출하기

첫 렌더링에서만 useEffect를 호출하는 방법이 있었습니다. 그럼 당연히 마지막 unmount에서만 호출하는 방법도 있겠죠? 있고말고요. 게다가 방식도 똑같습니다. 두번째 인자를 빈 배열로 주면 됩니다.

const UseEffectExample = () => {
  const [test, setTest] = useState('initial state');

  useEffect(() => {
    console.log('첫 렌더링에만 호출');
    return () => {
      console.log('마지막 언마운트 시 호출')
    }
  }, [])

  return (
    <div>
      <p>{test}</p>
      <input onChange={(e) => {setTest(e.target.value)}} />
    </div>
  )
}

function App() {
  const [useEffectRender, setUseEffectRender] = useState(true);

  return (
    <div className="App">
      {useEffectRender && <UseEffectExample />}
      <button onClick={() => {setUseEffectRender(!useEffectRender)}}>마지막 언마운트 호출하기!</button>
    </div>
  );
}

export default App;

자, 위의 코드는 마지막 언마운트 호출하기!버튼을 누르면 useEffect가 설정된 UseEffectExample컴포넌트가 unmount되도록 설정되어 있습니다. 로그를 확인하면 알겠지만, 아무리 test state의 값을 변경해서 unmount/mount하더라도 로그는 찍히지 않습니다. 하지만 버튼을 눌러서 해당 컴포넌트를 완전히 unmount시키면 로그가 찍히게 됩니다.

useeffect5

위의 이미지와 같이 말이죠.

자 이렇게 해서 useEffect에 대한 것을 알아 봤습니다. 원래는 useContext에 대해서도 설명하려고 했는데 글이 너무 길어졌네요. 다음 시리즈에서 계속 하겠습니다.

@Hyeonii
Copy link

Hyeonii commented May 27, 2021

설명이 이해가 쏙쏙 되네요~ 감사합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment