REACT HOOK

zenibako.lee
6 min readNov 11, 2019

--

from React 16.8 , React Native 0.59

Class를 작성할 필요 없이,

state와 react의 여러 기능을 사용할 수 있습니다.

hook은 lifecycle과 같은 React 개념에 좀 더 직관적인 API를 제공합니다.

만들어진 이유

State over components

React는 컴포넌트에 재사용 가능한 행동을 붙이는 방법을 제공하지 않습니다. 기존의 패턴을 사용할 때 컴포넌트를 재구성해야 하며 코드를 추적하기 어렵게 만듭니다.

(따라서 redux와 같은 state-container들이 서드파티에서 개발되었습니다.)

Hook는 계층 변화 없이 상태 관련 로직을 재사용할 수 있도록 도와줍니다.

Class

class가 코드의 재사용성과 코드 구성을 좀 더 어렵게 만들 뿐만 아니라, React를 배우는데 큰 진입장벽이라는 것을 알게 되었습니다.

예를 들어, js에서 this가 어떻게 작동하는지 알아야 했고,

event handler가 등록되는 방법에 대해 알아야 합니다. bind까지도

Hook개요

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>
);
}

버튼을 클릭하면, 값이 증가하는 counter예시가 있습니다.

‘useState’가 바로 Hook입니다.

Hook을 호출, function component안에 state를 추가했습니다.

이 state는 해당 component가 rerender되어도 유지됩니다.

useState는 현재 state값과 업데이트 함수를 쌍으로 제공합니다.

// 상태 변수를 여러 개 선언했습니다!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
// ...

하나의 컴포넌트 내에서 State Hook을 여러 개 사용할 수도 있습니다.

React는 useState 같은 내장 Hook을 몇 가지 제공합니다.
컴포넌트 간에 상태 관련 로직을 재사용하기 위해
Hook을 직접 만드는 것도 가능합니다.
일단 내장 Hook을 먼저 보겠습니다.

우리는 state의 변화를 통해 rerender를 해야 하지만,

어쩌다 dom자체를 조작하려는 행위를 합니다. 결국 오류가 발생하죠.

이 행위를 ‘side effect’라고 합니다. (anti-pattern)

해당 행위를 react의 철학에 반하지 않게 가능하게 해주는 것이
‘Effect Hook’ 입니다.

import React, { useState, useEffect } from 'react';// componentDidMount, componentDidUpdate와 비슷합니다
useEffect(() => {
// 브라우저 API를 이용해 문서의 타이틀을 업데이트합니다
document.title = `You clicked ${count} times`;
});

useEffect를 사용하면, React는 DOM을 바꾼 뒤에 “effect” 함수를 실행할 것입니다.

function FriendStatusWithCounter(props) {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});

const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});

function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
// ...

Hook을 사용하면 구독을 추가하고 제거하는 로직과 같이
서로 관련 있는 코드들을 한군데에 모아서 작성할 수 있습니다.

반면 class 컴포넌트에서는 생명주기 메서드(lifecycle methods)
각각에 쪼개서 넣어야만 했습니다.

클래스 컴포넌트는 count를 보여주기 위해 this.state.count를 사용합니다.

<p>You clicked {this.state.count} times</p>

반면 함수 컴포넌트는 count를 직접 사용할 수 있습니다.

<p>You clicked {count} times</p>

클래스 컴포넌트는 count를 갱신하기 위해 this.setState()를 호출합니다.

<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>

반면 함수 컴포넌트는 setCountcount 변수를 가지고 있으므로
this를 호출하지 않아도 됩니다.

<button onClick={() => setCount(count + 1)}>
Click me
</button>

그런데 useState의 return왜 array형태 일까요?

const [fruit, setFruit] = useState('banana');

바로 es6 의 특징중 하나인 destructure를 사용하기 때문입니다.

var foo = ["one", "two", "three"];

var [one, two, three] = foo;

--

--

zenibako.lee
zenibako.lee

Written by zenibako.lee

backend engineer, JS, Node, AWS

No responses yet