Hook 은 React 버전 16.8 부터 새로 추가된 React 요소이다.
Hook을 이용하여 기존 클래스 바탕의 코드를 작성할 필요 없이,
state 값과 여러 React 의 기능을 사용할 수 있다.
이에 대해 차근차근 알아보자. 🌊
등장배경
React Hooks 는 2018년 React Conf 에서 처음 발표되었다.
발표 당시 리액트가 겪는 가장 큰 3가지 문제점은 다음과 같다.
- Wrapping Hell
- Too many Components
- Class Component
첫번째 문제점인 Wrapping Hall 은 High Order Component 나
Children props 를 통해 연결되는 컴포넌트 구조들로 인해 너무 많은 계층이 생기고,
그로 인해 컴포넌트 관리가 점점 어려워진 것을 말한다.
두번째와 바로 연결하여 그렇게 컴포넌트가 복잡해지고, UI 상에서 제어할 것들이 많아지면서
세번째 문제점인 클래스를 컴포넌트를 사용해서 문제점이 발생한다는 것이다.
클래스에서 고려해야 하는 this 문장 규칙과 render 를 사용해 코드를 작성하는 과정이
사람과 기계 양방향 모두 혼란을 야기한다고 이야기하였다.
아래 코드는 각각 클래스 를 활용하여, Hooks 를 활용해 작성한 예시이다.
// state 를 사용하기 위해 기존 클래스를 사용하는 모습
class App extends React.Component{
state = {
count : 0
};
modify = n => {
this.setState({
count: n
});
};
render() {
const {count} = this.state;
return (
<>
<div>{count}</div>
<button onClick={() => this.modify(count + 1)}>Increment</button>
</>
);
}
}
⬇
// 위의 예시를 react hooks 활용해 작성
const App = () => {
const [ count, setCount ] = useState(0);
return (
<>
{count}
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
</>
);
}
React Hooks 란?
🌊 Ta - Da !
이렇게 해서 등장한 것이 React Hooks 이다 !
이는 React 의 state machine 에 연결하는 기본적인 방법으로,
클래스를 사용하지 않고 모든 것을 함수형 프로그래밍화 시켜준다.
기존에 state 를 사용하기 위해 클래스는 필수적이었는데,
Hooks 를 이용함으로써 function 내에서 매우 편리하게 state 를 사용할 수 있게 되었다.
더 자세히 말해보면,
Hook 은 함수 컴포넌트에서 React state와 생명주기 기능(lifecycler features)을
"연동(hook into)"할 수 있게 해주는 함수이다.
리액트는 useState 와 같은 내장 Hook 을 제공한다.
하지만 컴포넌트 간에 상태 관련 로직을 재사용하기 위해 Hook을 직접 만드는 것도 가능하다.
대표적인 내장 Hook인 useState 와 useEffect 에 대해서 알아보자.
[1] useState
아래 예시는 버튼을 클릭하면 값이 증가하는 간단한 카운터 함수이다.
import React, { useState } from 'react';
function Example() {
// "count"라는 새 상태 변수를 선언합니다
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}> Click me</button>
</div>
);
}
우리는 Hook 을 호출해 함수 컴포넌트 안에 state 를 추가했다.
이 state 는 컴포넌트가 다시 렌더링 되어도 그대로 유지된다.
useState는 함수형 컴포넌트에서 상태를 관리할 수 있도록 해준다.
이는 현재의 state 값과 이 값을 업데이트하는 함수를 쌍으로 제공한다.
이 함수를 핸들러나 다른 곳에서 호출할 수 있다.
const [state, setState] = useState(initialState);
초기에 state 를 세팅하는 initialState 옵션이 제공된다.
state 변수는 직접 변경하는 것이 아니라 useState 함수에서 반환한 setter 함수를 이용해야 한다!
setter 함수의 return 타입은 void 혹은 값의 설정 결과를 알려줄 수 있는 타입이어야 한다.
이는 클래스에서 사용하는 this.setState와 유사하지만,
이전 state와 새로운 state를 합치지 않는다는 차이점이 존재한다.
더 자세한 내용을 보고 싶다면 📜공식문서 를 정독해보자
[2] useEffect
React 컴포넌트 안에서 데이터를 가져오거나 구독하고,
DOM 을 직접 조작하는 모든 동작을 "side effect == effect" 라고 한다.
이는 다른 컴포넌트에 영향을 줄 수도 있고, 렌더링 과정에서는 구현할 수 없는 작업이기 때문이다.
Effect Hook, 즉 useEffect 는 함수 컴포넌트 내에서 이러한 side effects를 수행할 수 있게 해준다.
React 의 클래스 생명주기 메서드와 연관시켜 생각해보면,
useEffect Hook = componentDidMount + componentDidUpdate + componentWillUnmount
위와 같다고 생각하면 된다 !
아래 예시는 useState 에서 사용한 카운터 예시를 바탕으로,
클릭 횟수가 포함된 문장으로 문서의 타이틀에 표현할 수 있는 기능이 포함되었다.
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// componentDidMount, componentDidUpdate와 같은 방식으로
useEffect(() => {
// 브라우저 API를 이용하여 문서 타이틀을 업데이트한다.
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}> Click me </button>
</div>
);
}
기존에 클래스 안에서 생명주기 메서드를 사용할 떄보다 훨씬 간결함을 볼 수 있다.
이같은 useEffect 의 원형을 보면 다음과 같은데,
import { useEffect } from 'react';
useEffect(function, deps);
2개의 인자 중 첫번째는 function 으로써의 effect 이며,
두번째 인자는 deps 로 이는 componentWillUpdate 와 연관이 있다.
deps (dependency) 를 빈 배열로 보낸다면, 최초 1회만 실행한다.
하지만 deps 에 값을 넣는다면, 해당 값이 변할 때만 (componentWillUpdate)
해당 useEffect 가 활성화(componentDidMount) 된다.
추가로, Effect 를 해제할 필요가 있다면, 해제하는 함수를 반환 (return) 해주면 된다,.
이는 선택적인 작업으로, 필요에 따라 사용한다.
더 자세한 내용을 보고 싶다면 이 또한 📜공식문서를 정독해보자.
© 참고
https://ko.reactjs.org/docs/hooks-intro.html (React Hooks 공식문서)
https://nomadcoders.co/react-hooks-introduction/lobby (노마드코더 React Hooks 강의)
Hook의 개요 – React
A JavaScript library for building user interfaces
ko.reactjs.org
'Project > softsphere' 카테고리의 다른 글
[React] 비동기 처리 방식 Async & Await (+ Promise) (0) | 2021.10.18 |
---|---|
[React] JSX (JavaScript eXtension) 란? (0) | 2021.10.16 |
[React Native] React Native Paper (0) | 2021.10.08 |
[React Native] WebView 동작 흐름 이해하기 (0) | 2021.10.03 |
[!React Native] Chocolatey 설치 (feat. sudo / locate32 사용법) (0) | 2021.10.01 |