[TIL 37] React Hook과 상태 관리

yezo cha·2021년 7월 8일
0

React

목록 보기
7/8
post-thumbnail

React Hook

Hook은 리액트 컴포넌트에서 상태와 이펙트를 도입하고 관리하는 효과적인 매커니즘.

Hook이 등장하면서 더 이상 상태를 관리하기 위해서 Class를 사용할 필요가 없어졌다.
기존에는 Class형 컴포넌트에서만 상태를 관리할 수 있었다.
함수형 컴포넌트에서는 상태를 관리할 수 없었지만, Hook을 통해 상태 관리를 할 수 있게 되었고, 기존 클래스형 컴포넌트에서만 가능하던 여러 기능을 사용할 수 있게 되었다.

  • Hook 규칙
    • 가장 상위에서만 훅을 호출해야 한다.
      • 반복문, 조건문, 중첩된 함수 내에서 훅을 호출하지 말자.
      • 대신, 리액트 함수 가장 상위 레벨에서 훅을 사용해야 한다.
      • 컴포넌트가 렌더링 될 때마다 동일한 순서로 훅이 호출된다.
    • 리액트 함수에서만 훅을 호출할 수 있다.

useState

useStatestate Hook이다.
state를 편하게 관리할 수 있는 가장 기본적인 API.
useStatestatesetState()로 나뉘며 초기에 initialValue를 받고, 해당 초기값은 처음 렌더링시에만 사용한다.

Hook은 쉽게 말하자면, 함수 컴포넌트에서 React state와 생명주기 기능(lifeCycle features)을 연동(hook into)할 수 있게 해주는 함수이다.
Hook을 통해 class 없이 리액트를 사용할 수 있다.

import React, { useState } from 'react'

function App() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onclict={() => setCount(count + 1)}>Click me!</button>
    </div>
  )
};

useEffect

useEffecteffect Hook으로, 함수 컴포넌트에서 사이드 이펙트를 다룰 수 있게 해준다. 동기화

React Class의 componentDidMount;처음 나타났을 때, componentDidUpdate;특정 props가 바뀔 때, componentWillUnmount;사라질 때와 같은 목적으로 제공되지만 하나의 API로 통합된 것.
리액트는 기본적으로 렌더링 이후에 effect를 실행한다.

effect함수는 컴포넌트 내에 있기 때문에 props와 state에 접근할 수 있다.
첫번째 렌더링과 이후 업데이트가 될 때 마다 effect가 수행된다.

정리
1. 화면이 처음 떴을 때 실행
- deps에 빈 배열[]을 넣을 때.
- lifeCycle 중 componentDidmount처럼 실행.
2. 화면이 사라질 때 실행. (cleanup 함수)
- componentWillUnmount처럼 실행.
3. deps에 넣은 파라미터값이 업데이트 되었을 때 실행.
- componentDidUpdate처럼 실행.

마운트 / 언마운트

useEffect를 사용할 때, 첫번째 파라미터에는 함수, 두번째 파라미터에는 의존값이 들어있는 배열deps을 넣는다.
만약에 deps배열을 비워둔다면, 컴포넌트가 처음 나타날 때에만 useEffect에 등록한 함수가 호출된다.

useEffect에서는 함수를 반환할 수 있는데 이를 cleanup 함수라고 부른다.
cleanup 함수는 useEffect에 대한 뒷정리를 해준다고 이해하자.
deps가 비어있는 경우에는 컴포넌트가 사라질 때 cleanup 함수가 호출된다.

import React, { useEffect } from 'react';

function User({ user, onRemove, onToggle }) {
  useEffect(() => {
    console.log('컴포넌트가 화면에 나타남');
    return () => {
      console.log('컴포넌트가 화면에서 사라짐');
    };
  }, []);
  
  return (
    <div>
      <b
        style={{
          cursor: 'pointer',
          color: user.active ? 'green' : 'black'
        }}
        onClick={() => onToggle(user.id)}
      >
        {user.username}
      </b>
      &nbsp;
      <span>({user.email})</span>
      <button onClick={() => onRemove(user.id)}>삭제</button>
    </div>
  );
}

function UserList({ users, onRemove, onToggle }) {
  return (
    <div>
      {users.map(user => (
        <User
          user={user}
          key={user.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
}

export default UserList;

마운트 시에 하는 작업

  • props로 받은 값을 컴포넌트의 로컬 상태로 설정.
  • 외부 API 요청(REST API 등..)
  • 라이브러리 사용 (D3, Video.js 등..)
  • setInterval을 통한 반복작업 또는 setTimeout을 통한 작업 예약

언마운트 시에 하는 작업

  • setInterval, setTimeout을 사용하여 등록한 작업들 clear하기 (clearInterval, clearTimeout)
  • 라이브러리 인스턴스 제거

deps에 특정값 넣기

deps에 특정 값을 넣는다면 컴포넌트가 처음 마운트 될 때에도 호출이 되고, 지정한 값이 바뀔 때에도 호출이 된다.
deps 안에 특정 값이 있다면 언마운트시에도 호출이 되고, 값이 바뀌기 직전에도 호출이 된다.

import React, { useEffect } from 'react';

function User({ user, onRemove, onToggle }) {
  useEffect(() => {
    console.log('user 값이 설정됨');
    console.log(user);
    return () => {
      console.log('user 가 바뀌기 전..');
      console.log(user);
    };
  }, [user]);
  return (
    <div>
      <b
        style={{
          cursor: 'pointer',
          color: user.active ? 'green' : 'black'
        }}
        onClick={() => onToggle(user.id)}
      >
        {user.username}
      </b>
      &nbsp;
      <span>({user.email})</span>
      <button onClick={() => onRemove(user.id)}>삭제</button>
    </div>
  );
}

function UserList({ users, onRemove, onToggle }) {
  return (
    <div>
      {users.map(user => (
        <User
          user={user}
          key={user.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
}

export default UserList;

useEffect안에서 사용하는 state나 props가 있다면, useEffectdeps에 넣어주어야 한다.
그렇지 않으면, useEffect에 등록한 함수가 실행 될때 최신 props, state를 가리키지 않게 된다.

deps 파라미터 생략하기

deps 파라미터를 생략한다면 컴포넌트가 리렌더링 될 때마다 호출이 된다.

profile
(ง •̀_•́)ง

0개의 댓글