본문 바로가기
Programming Step/React JS

React Hook

by eclipse7727 2021. 6. 20.

react hook의 지원은 클래스보다 함수를 선호하는 사람에게 좋은 일이다. 기존의 코드를 다시 작성할 필요 없이 일부의 컴포넌트들 안에서 훅을 사용할 수 있다. 그렇기에 훅이 당장 필요하지 않다면 사용할 필요는 없다. 이전 버전과 100퍼센트 호환성을 가지고 있다.

useState

useState는 state를 함수 컴포넌트 안에서 사용하게 해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Example extends React.Component {
  constructor(props) {
    super(props);
  this.state = {
    count: 0
  };
}
 
 
import React, { useState } from 'react';
function Example() {
// state 변수인 count 선언
const [count, setCount] = useState(0);
cs

Component의 State는 Lifetime에 따라 변경될 수 있는 정보를 보유한 객체이며,

위의 두 코드와 같이 class에서의 state와 react hook의 state는 같다.

useEffect

class에서는 componentDidMount(), componentDidUpdate() 등을 사용하였지만 아래와 같이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Example extends React.Component {
 
    constructor(props) {
 
      super(props);
 
      this.state = {
 
        count: 0
 
      };
 
    }
 
   componentDidMount() { // 처음 마운트 될 때 작동
 
     document.title = `You clicked ${this.state.count} times`;
 
   }
 
   componentDidUpdate() { // 마운트 된 이후 state값이 업데이트 될 때 작동
 
     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 })}> // 버튼이 클릭 되면 count의 값을 1 증가 시킴.
 
            Click me
 
          </button>
 
        </div>
 
      );
 
    }
 
  }
cs

 

  

개념적으로는 렌더링 이후에 항상 같은 코드가 수행하도록 짜 놓은 것이나, class component 에서는 코드가 중복되어도 해결 할 만한 메소드가 따로 없다.

리액트 훅은 useEffect라는 함수로 해결이 가능하다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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)}> // 버튼 클릭시 count값 1 증가
 
        Click me
 
      </button>
 
    </div>
 
  );
 
}
cs

위 코드는 앞서 보여드린 class버전 코드와 일치한다. 더 짧고 직관적이며 중복을 제거하기에 더 나아진 모습이다. useEffect는 기본적으로 첫 렌더링과 그 이후의 모든 업데이트에서 수행된다. 일종의 마운팅과 업데이트 방식을 더 한것이라 보면 된다.

 

useCallback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function Component() {
 
    const [count, setCount] = React.useState(0)
 
    const handleClick = React.useCallback(
 
      () => console.log('current count :' + count),
 
    [count]) 
 
// useCallback이 없다면 
 
// useCallback 사용 다만 2번째인자가 없을 때 count 값이 바뀌더라도 출력 갱신이 안될 수 있음
 
  
 
    return (
 
      <>
 
        <button onClick={() => setCount(count + 1)}>카운트 올리기</button>
 
        <button onClick={handleClick}>클릭해보세요!</button>
 
      </>
 
    )
 
  }
cs

 

위의 코드에 usecallback이 없다면 컴포넌트가 렌더링 될 때마다 함수를 새로 생성하며, 부모 컴포넌트가 렌더링되거나, 상태(state)가 변경되는 경우 리렌더링을 유발한다.

 

useCallback으로 함수를 감싸주면 일종의 함수를 저장해 놨기에 그대로 가져다 재사용 할 수있어서 효율적이다. 이는 메모이제이션 패턴을 사용한 것이다. 메모이제이션은 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복을 제거하여 최적화 하는 기술이다.

 

useCallback의 2번째 인자 에는 함수가 의존하는  값이 변경 되었을 경우 저장된 함수를 갱신해야하기에 만들어 놓은 것이다. 코드처럼 useCallback 함수 내부에서 의존하는 상태값이 있다면, 반드시 두번째 인자 배열에 명시해야한다.

useMemo

useCallback과 같지만 useCallback은 함수를 반환한다는 것이고 useMemo는 값을 반환 한다는 것이다.

예제는 아래와 같다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Component() {
 
    const [count, setCount] = React.useState(0)
 
    const doubleCount = React.useMemo(() => count * 2, [count])
 
    console.log(doubleCount) // 두배로 계산한 값 출력
 
    return (
 
      <>
 
        <button onClick={() => setCount(count + 1)}>카운트 올리기</button>
 
      </>
 
    )
 
  }
cs

 

count값과 무관하게 컴포넌트가 재렌더링 되었을 경우 불필요한 연산을 하게된다.

컴포넌트의 상태값이 많고 복잡한 연산의 경우 최적화가 필요하다.

1
2
3
const handleClick = React.useMemo(
    () => () => console.log('current count :' + count),
[count]) // useMemo로 useCallback 구현 
cs

위 코드는 useMemo로 useCallback을 구현한 것이다.

 

반응형

댓글