akjfal

Effect Hook 사용하기 본문

(구)React 공식문서/HOOK

Effect Hook 사용하기

akjfal 2023. 3. 5. 22:07

Effect Hook 사용하기

<aside> 💡 useEffect는 class에서 componentDidMount, componentDidUpdate, componentWillUnmount가 합쳐진 방식이라고 생각하면 된다.

</aside>

React에는 두 종류의 side effects가 존재하는데 clean-up이 필요한 것과 필요 없는 것 두가지가 있다.

clean-up이 필요 없는 Effects

class형에서 어떠한 데이터를 업데이트 하기 위해서는 컴포넌트가 방금 마운트 되엇는지(componentDidMount), 업데이트되었는지(componentDidUpdate)에 상관없이 모든 동작을 수행해줘야 할 수도 있습니다.

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

만약 위 코드에서 componentDidMount가 없으면 처음 렌더링 되었을 때 title이 기본 값인 상태가될 것이고, componentDidUpdate가 없으면 버튼을 눌렀을 때 title이 바뀌지 않을 것입니다.

따라서 같은 함수를 중복으로 적어줘야 하는 경우가 생기게 됩니다.

하지만 useEffect의 경우에는 한번에 처리가 가능합니다.

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

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

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect가 하는일

컴포넌트가 렌더링 된 이후에 작동해야 하는 함수(effect)를 기억했다가, DOM 업데이터 이후 불러와 실행합니다.

useEffect를 컴포넌트 안에서 불러내는 이유

effect를 통해서 컴포넌트 내부의 state나 props를 접근해서 처리 할 수 있기 때문입니다.

useEffect는 렌더링 이후 매번 수행 되나요?

기본적으로 처음가 모든 업데이트에서 수행되지만, 의존성 값을 통해서 조절 할 수 있습니다. class의 마운팅과 업데이트라는 생각은 이제 버리시고, effect를 렌더링 이후에 발생시킨다. 라고 생각하시면 됩니다.

useEffect(callback, [dependency])

좀 더 깊은 설명

  • useEffect에 전달되는 callback 함수는 모든 렌더링에서 다른 함수입니다. 이유는 내부의 값이 업데이트 되었는지 등 사이트 이펙트를 방지하기 위해서 의도된 방식이기 때문입니다.
  • componentDidMount, componentDidUpdate와 달리 useEffect의 effect는 브라우저가 화면 업데이트 하는 것을 막지 안항 반응성을 향상시킵니다.

Clean-up을 이용하는 Effects

만약 컴포넌트가 언마운트 될 때 메모리 누수 방지를 위해서 setTimeout을 해지하는 등의 작업이 필요한 경우가 있습니다.

class FriendStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOnline: null };
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
  handleStatusChange(status) {
    this.setState({
      isOnline: status.isOnline
    });
  }

  render() {
    if (this.state.isOnline === null) {
      return 'Loading...';
    }
    return this.state.isOnline ? 'Online' : 'Offline';
  }
}

위의 코드에서도 componentDidMount와 componentWillUnmount를 통해서 컴포넌트가 처음 만들어질 때와 사라질 때 동작을 지정해주고 있습니다.

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

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// effect 이후에 어떻게 정리(clean-up)할 것인지 표시합니다.
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

이를 useEffect에서는 함수를 return 시켜줘서 동작 하게 합니다.

이러한 함수 반환을 clean-up이라 부릅니다.

componentUnMount와 동일하게 컴포넌트의 파운트가 해제될 때 실행됩니다.


effect가 업데이트 마다 실행되는 이유

class형에서는 내부 값들이 업데이트 되었을 때 실행되도록 처리해주기 위해서 componentDidUpdate를 사용해주고 있습니다. 이를 사용하지 않으면 값이 바뀐 것을 대처할 수 없기 때문입니다. 하지만 effect가 업데이트마다 실행되고, 새로운 함수들을 실행시켜 일관성을 유지 해줄 수 있습니다.

내부 동작 방식을 보면

  • 처음 데이터 값 렌더링 {state : 100} state == 100이라고 가정
    • effect 실행
  • 데이터 값 업데이트 {state: 200} 으로 변경
    • 기존 effect를 clean-up (state가 100인 effect)
    • 신규 effect 실행(state가 200인 effect)
  • 마운트 해제
    • 기존 effect를 clean-up (state가 200인 effect)

방식으로 흘러가서 일관성을 유지해줍니다.

성능 최적화 시키기

아마 useEffect를 사용하시면서 대다수는 []를 사용했을것입니다. []의 경우에는 배열안에 들어가 있는 값들을 비교해서 effect를 실행 여부를 결정합니다.

또한 배열안에 있는 값들중 하나라도 변경시 effect는 동작하며, clean-up도 동일하게 작동합니다.

'(구)React 공식문서 > HOOK' 카테고리의 다른 글

Hook API 참고서  (0) 2023.03.05
Hook의 개요  (0) 2023.03.05
Hook API 참고서  (0) 2023.02.16
Hook의 개요  (0) 2023.02.16
Effect Hook 사용하기  (0) 2023.02.16
Comments