Hook
에는 앞선 포스팅에서 소개한 useState
, useEffect
외 다양한 Hook API
가 존재한다.
이번 포스팅에서는 다양한 Hook API
를 소개하면서 사용해보겠다.
useMemo
는 콜백함수의 값을 기억하여 재실행을 방지
앞선 포스팅에서 설명했듯 state
가 변화하면 클래스 방식에서는 render()
함수가, Hook
에서는 함수 전체가 재실행된다.
그 과정에서 불필요한 메모리누수, 데이터낭비등의 악영향이 발생하는데 이 때 useMemo
를 사용하면 다시 실행되는 값을 기억하여 코드가 재실행되지 않게 방지한다.
useMemo
는 useEffect
처럼 콜백함수
, 변화값[]
두가지 인자를 사용하며 변화값[]
이 바뀌지 않는다면 콜백함수
는 재실행되지 않고 변하면 다시 실행된다.
useMemo
의 사용방법은 아래와 같다.
const style = useMemo(() => (
{ marginTop: 10 }
), []);
<button style={style} >Click Me</button>
useCallback
은 콜백함수 자체를 기억하여 재실행을 방지
앞서 소개한 useMemo
는 함수의 리턴값을 기억하고 재실행을 방지했지만 useCallback
은 함수 자체를 기억한다.
useCallback
또한 마찬가지로 다시 실행되는 함수를 기억해서 리랜더링될 때 함수 재생성을 통한 데이터 낭비를 방지한다.
사용법 또한 useMemo
와 동일하게 콜백함수
, 변화값[]
두가지 인자를 사용한다.
useCallback
의 사용방법은 아래와 같다.
const onClickBtn = useCallback(() => (
console.log('Clicked!!');
), []);
<button onClick={onClickBtn} >Click Me</button>
앞서 설명한 useEffect
, useMemo
, useCallback
이 3가지 API는 비슷하지만 아래와 같은 차이점이 존재한다.
useEffect(콜백함수
, 변화값[]
) : 변화값[]
이 바뀔때 callback을 실행한다.
useMemo(콜백함수
, 변화값[]
) : 변화값[]
이 바뀔때까지 callback의 값을 기억한다.
useCallback(콜백함수
, 변화값[]
) : 변화값[]
이 바뀔때까지 callback함수 자체를 기억한다.
useRef
는 특정DOM Element
를 컨트롤
JavaScript
에서는 특정 DOM
를 선택할 때 getElementById
, querySelector
를 사용했다.
React
에서는 위와 같은 상황에서 useRef
를 통해 특정 DOM Element
를 컨트롤한다.
아래 예제는 useRef
를 통해 input
에 focus
를 설정한다.
onSubmitForm = () => {
// focus사용할 부분에 적용
input.focus();
}
// ref를 위한 input변수
input;
<form onSubmit={onSubmitForm}>
<input ref={(c) => this.input = c} />
</form>
useReducer
는redux
의reducer
개념을React
에서 사용
useReducer
는 상태관리 라이브러리인 redux
의 핵심 개념인 reducer
의 React
버전이다.
개발에 규모가 커짐에 따라 state
, setState
가 증가하는데 이를 효과적으로 관리하기 위해 하나의 state
, setState
로 통일한다.
주로 소규모 작업시에는 usereducer
, contextapi
를 활용하여 redux
를 대체하고, 큰규모에서는 비동기를 처리하기 위해 redux
사용한다.
useReducer
를 사용하기 위한 구성요소들은 다음과 같다.
useReducer
의 기본형태는 아래와 같으면 다음과 같은 구성요소들을 포함한다.
const [state, dispatch] = useReducer(reducer, initialState);
state
: 컴포넌트에 사용되는 상태
dispatch
: reducer
함수 인자를 실행하여 state
를 업데이트한다.
reducer
: 현재 state
, action
객체를 인자로 받아 기존의 state
를 새로운 state
로 반환한다.
initialState
: 초기 state
dispatch
는 state
를 변화하는 action
객체를 인자로 받아 reducer
함수를 실행한다.
전달받은 action
객체에는 type
과 작업과 관련된 데이터를 포함하며 이를 통해 컴포넌트 내에서 state
를 변화시킨다.
단 dispatch
는 state
를 비동기적으로 변경한다. 그래서 만약 동기적으로 state
를 변경하고 싶다면 상태관리 라이브러리인 redux
를 사용해야 한다.
// action.type은 오타 방지를 위해 상수 변수로 사용
const ADD_TO_SHOPPINGLIST = 'ADD_TO_SHOPPINGLIST';
// 리랜더링을 방지하기 위해 객체는 useCallback을 사용
const onClickBtn = useCallback(() => {
dispatch({ type: ADD_TO_SHOPPINGLIST, data: 1 });
}, []);
<button onClick={onClickBtn}>+</button>
dispatch
를 통해 실행된 reducer
는 state
, action
을 인자로 받아 이를 통해 새로운 state
를 return
한다.
새로운 state
반환시에는 불변성을 유지하기 위해 얕은 복사하여 변경하고자 하는 대상만 변경해야 한다.
만약 불변성을 유지하지 않는다면 React
는 state
의 변화를 탐지하지 못해 리랜더링을 수행하지 않는다.
const reducer = (state, action) => {
switch (action.type) {
case ADD_TO_SHOPPINGLIST:
return {
...state,
count: state.count + action.data
};
}
}
아래 예제는 useReducer
를 사용하여 장바구니 기능을 구현한다.
import React, { useCallback, useReducer } from "react";
const initialState = {
name: '맛있는 사과',
count: 0
};
const ADD_TO_SHOPPINGLIST = 'ADD_TO_SHOPPINGLIST';
const reducer = (state, action) => {
switch (action.type) {
case ADD_TO_SHOPPINGLIST:
return {
...state,
count: state.count + action.data
};
}
}
const ShoppingList = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const onClickBtn = useCallback(() => {
dispatch({ type: ADD_TO_SHOPPINGLIST, data: 1 });
}, []);
return (
<>
<h2>{state.name}</h2>
<h2>{state.count}개 주문</h2>
<button onClick={onClickBtn}>+</button>
</>
);
};
export default ShoppingList;