React.org - Hook

EllaDev·2022년 1월 22일
0

React 공식문서

목록 보기
2/2

해당글은 React공식문서를 바탕으로 쓰여진 것이며 그외에 참고한 문서는 따로 Reference를 쓰도록하겠다.

Hook

Hook이란?

정의
함수 컴포넌트에서 React state와 lifecycle features을 "연동(hook into)"할 수 있게 해주는 함수

  • class안에서는 작동 안한다.
  • React 16.8버젼에 새로 추가 되었다.(이후 모든 패키지를 업그레이드해야한다.)


built-in Hooks

State Hook

예제코드
state 변수 선언
클래스에서는 constructor안에서 this.state를 설정하고 초기화 했지만 함수 컴포넌트에서는 이게 불가능하기 때문에 useState를 컴포넌트에 호출하여 State를 설정하고 초기화한다.

useState

  • function component에서 state를 사용할 수 있게 해준다.
  • state값을 업데이트 해주는 함수는 이벤트 핸들러나 다른 컴포넌트에서도 사용될 수있다.
  • class의 this.state가 제공하는 기능과 같다.
  • 인자값으로 state의 초기값을 넘겨준다.
  • state변수와 state변수를 업데이트하는 함수를 반환한다. 이는 this.state.countthis.setState와 유사하다.
import React, { useState } from 'react';

function ExampleWithManyStates() {
  // 상태 변수를 여러 개 선언했습니다!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
  
  /* 배열구조분해를 하지 않는다면 */
  var fruitStateVariable = useState('banana'); 
  var fruit = fruitStateVariable[0]; 
  var setFruit = fruitStateVariable[1];
}

this.setState와 setState(setAge...)가 다른점
this.setState와 setState는 많은 부분이 같지만 state 갱신하는 방법이 다르다.
this.setState는 state를 병합하는 것이지만 setState는 대체하는 것이다.


Effect Hook

  • React 16.8버전에 새로 추가
  • Effect Hook을 사용하면 함수 컴포넌트에서 side effect를 수행 가능하다.
  • React의 class 생명주기의 componentDidMount와 componentDidUpdate, componentWillUnmount가 합쳐진 것이 useEffect 이다.

정리(Clean-up)를 이용하지 않는 Effects

  • React가 DOM을 업데이트한 뒤 추가로 코드를 실행해야 하는 경우에 실행이후에 정리가 필요없을 수 있다.
  • EX) 네트워크 리퀘스트, DOM 수동 조작, 로깅 등

Class 컴포넌트를 이용한 예시

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>
    );
  }
}
  • class 컴포넌트는 render 메서드 자체로는 side effect를 발생시키지 않고 Dom을 업데이트하고 난 후에 effect를 수행한다.
    그래서 componentDidMount와 componentDidUpdate를 모두 사용한다.
  • 위 코드 class 안의 componentDidMount와 componentDidUpdate에 같은 코드가 중복된다. 개념적으로 렌더링 이후에 같은 코드가 수행되어야하지만 이를 감지하는 메서드는 React에 없다.

Hook을 사용한 예시

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가 하는 일
    • 컴포넌트가 렌더링 이후에 수행해야하는 일을 지시하는 일을 한다.
    • React는 넘긴 함수(‘effect’)를 기억했다가 DOM 업데이트를 수행한 이후에 불러낸다.
  • useEffect를 컴포넌트 안에서 불러내는 이유
    • 컴포넌트 안에 state변수와 props에 접근 가능하다.
    • 함수 범위 안에 존재하기 때문에 특별한 API 없이도 값을 얻을 수 있다.
    • 자바스크립트의 클로저를 이용하여 자바스크립트가 이미 가지고 있는 방법을 이용하여 문제를 해결한다.
  • useEffect는 effect를 렌더링 이후에 발생하는 것으로 effect가 수행되는 시점에 이미 DOM이 업데이트되었음을 보장한다.
  • useEffect에 전달된 함수가 모든 렌더링에서 다르다. 이는 리렌더링마다 모두 이전과 다른 effect로 교체하여 전달되기 때문이다. 이 점이 렌더링의 결과의 한 부분이 되게 만드는 점인데, 각각의 effect는 특정한 렌더링에 속한다.

정리(clean-up)를 이용하는 Effects

  • 외부 데이터에 구독(subscription)을 설정해야 하는 경우 메모리 누수가 발생하지 않도록 정리(clean-up)해야한다.

Class 컴포넌트를 사용하는 예시

  • 아래 코드는 class를 이용하여 상태를 구독(subscribe)하고 보여주는 코드이다.( ChatAPI 모듈의 예)
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';
  }
}

Hook을 사용하는 예시

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';
}
  • effect에서 함수를 반환하는 이유 :
    • 추가적인 정리(clean-up) 메커니즘으로 모든 effect는 정리를 위한 함수를 반환할 수 있다.
    • 구독(subscription)의 추가와 제거를 위한 로직을 가까이 묶어두어 모두 하나의 effect를 구성하는 것한다.
  • effect를 정리(clean-up)하는 시점
    • 컴포넌트가 마운트 해제되는 때에 정리(clean-up)를 실행
    • effect는 렌더링 될때마다 실행되기 때문에 다음 렌더링이 실행되기전에 이전 effect는 정리된다. 이는 버그 방지에 도움이 된다.
profile
Frontend Developer

0개의 댓글