React Hook
Post

React Hook

Hook은 React 버전 16.8에서 새로 추가되었다.

Hook은 함수 컴포넌트에서 React state와 생명주기 기능을 연동할 수 있게 해주는 함수이다.

Hook은 class안에서는 동작하지 않기 때문에 Class형 컴포넌트가 아닌 function형 컴포넌트를 사용하여 간단하게 컴포넌트를 작성할 수 있고 state도 관리할 수 있다.

useState

useState는 현재의 state값과 이 값을 변경할 수 있는 함수 두가지의 값을 가진다.

이 함수를 이벤트 핸들러나 다른 곳에서 호출할 수 있다.

class의 this.setState와 거의 유사하나, 이전 state와 새로운 state를 합치지 않는다는 차이점이 있다.

1
2
3
4
5
6
7
8
import React, { useState } from 'react';

function ExampleWithManyStates() {
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}

useState는 인자로 ()안에 초기 state값을 하나 받는다.
this.state와 달리 객체일 필요는 없지만, 객체로 초기화도 가능하다.

또한 하나의 컴포넌트 내에서 state Hook을 여러 개 사용할 수도 있다.

useEffect

side effects란 컴포넌트 안에서 데이터를 가져오거나 DOM을 직접 조작하는 작업 등의 모든 동작을 의미한다.

useEffect는 함수 컴포넌트 내에서 이런 side effects를 수행할 수 있게 해준다.

React class의 componentDidMount, componentDidUpdate, componentWillUnmount와 같은 목적으로 제공되지만, 하나의 API로 통합된 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 Hook을 이용하면 React에게 컴포넌트가 렌더링 이후에 어떤일을 수행해야하는 지 알릴 수 있다.

useEffect는 컴포넌트 안에서 작성해야 하는데 const state변수에 접근하기 위해서이다.
함수 범위 안에 존재하므로 특별한 API 없이 값을 얻을 수 있다.

useEffect도 관련 없는 로직들을 따로 작성하기 위해 여러번 사용할 수 있다.

Hook 규칙

Hook을 사용하기 위해서는 두가지 규칙을 준수해야 한다.

  1. 최상위에서만 Hook을 호출해야 한다. 반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하면 안된다.

    그래야 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장된다.

  2. 오직 React 함수 내에서 Hook을 호출해야 한다. Hook을 일반적인 Javascript 함수에서 호출하면 안된다.

사용자 정의 Hook

자신만의 Hook을 만들어 컴포넌트 로직을 함수로 뽑아내어 간단하게 재사용할 수 있다.

사용자 정의 Hook의 이름은 use로 시작되어야 한다.

1
2
3
4
5
6
7
8
9
const CustomHook = ()=>{
  const [name,setName] = useState('');

  return(
    <>
      <div value={name} onChangeText={setName} onReset={()=>setName('')}></div>
    </>
  )
}

setName()을 중복적으로 사용할 경우 커스텀 hook을 만들어 중복을 줄일 수 있다.

1
2
3
4
5
6
7
8
9
10
const useInput = (initialValue)=>{
  const [value,setValue] = useState(initialValue);
  const resetValue = ()=> setValue(initialValue);

  return{
    value,
    setValue,
    resetValue,
  }
}

위처럼 useInput이라는 커스텀 훅을 만들면 다음과 같이 사용할 수 있다.

1
2
3
4
5
6
7
8
9
const CustomHook = ()=>{
  const [value:name,setValue:setName, resetValue:resetName] = useInput('');

  return(
    <>
      <div value={name} onChangeText={setName} onReset={()=>{resetName}}></div>
    </>
  )
}

Name 하나만 사용한다면 useState를 사용해도 되겠지만 age, address, text 모두 위처럼 onChangeText, onReset 와 같은 기능이 필요할 경우에는 반복되고 번거로워질 수 있어 유용하다.

구조분해 할당 내부에서 변수 이름을 콜론(:)을 사용해서 다른이름으로 바꾸어 사용할 수도 있다.

참고