일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- ios
- 코딩테스트
- Xcode
- TypeScript
- 자바스크립트
- JavaScript
- Apple Developer Academy
- velog
- NextJs
- 코드트리
- react
- globalcommunity
- AppleDeveloperAcademy
- 코딩테스트실력진단
- 회고
- 프론트엔드
- SWIFT
- swiftUI
- 프로젝트
- iOSDeveloper
- 프로그래머스
- frontend
- react-query
- 알고리즘
- tshaped
- Front-end
- git
- UIKit
- error
- 코드트리챌린지
- Today
- Total
Moon Work
Custom hook 기초 본문
시작하며
React를 통해 개발하면서 컴포넌트마다 똑같은 코드가 반복되곤 하는데 그런 코드가 심지어 길이도 작지 않다면 컴포넌트가 길어져서 곤란하다. 이런 문제를 custom hook을 통해 해결할 수 있는 부분이 있을 것이라 생각이 들어 새로 공부하게 되었다.
Custom hook의 장점
- 클래스 컴포넌트보다 적은 코드로 동일한 기능을 구현할 수 있다.
- 코드 길이를 줄이면서 가독성은 높일 수 있다.
Custom hook 규칙
- 최상위에서 hook을 호출한다 (반복문이나 조건문에서 hook을 호출하지 않는다.)
- React 함수 내에서만 hook을 호출한다.
- hook의 이름을 'use'로 시작한다.
Hook 만들 때 고려해야 하는 점
- custom hook을 만들 때는 다른 hook의 state에 영향을 끼치게 해서는 안된다. 즉, 각각의 state가 고유성을 가지고 있어야 하는데 고유성을 지키지 않는 경우 예기치 못한 문제나 이슈가 발생했을 때 그 원인을 파악하기도 어렵다.
- custom hook이 에러나 코드를 보는데 있어서 인과관계를 잘 파악할 수 있게 해야 한다.
기존에 쓰던 반복되는 로직을 가능하면 custom hook으로 깔끔하게 만들려고 했는데 그랬다가는 가독성이나 오히려 hook을 수정하는데 더 시간이 걸리고 에러도 발생하겠다는 생각이 들었다. 그러면 어떤 상황에서 hook을 사용하는게 좋을지 궁금해서 좋은 custom hook의 예리를 추가로 정리해보았다.
좋은 custom hook 예시
1. Enter / Esc key hook
특정 버튼이 클릭하고 클릭하지 않는 것에 대해 핸들링하는 부분의 로직이 길어졌는데 아래 hook을 통해 로직을 줄일 수 있고 또 다른 상태와 state 역시 겹치지 않는 다는 점에서 고유성을 지킨 예시인 것 같다.
import { useEffect } from 'react';
interface IUseEnterEscButtonsProps {
handleCancel: Function,
handleConfirm: Function,
}
export const useEnterEscButtons = ({handleCancel, handleConfirm}:IUseEnterEscButtonsProps)=>{
useEffect(()=>{
const listener = (event: {code:string, preventDefault: ()=>void}) => {
if((event.code === 'Enter' || event.code === 'NumpadEnter')){
handleConfirm();
event.preventDefault();
}
}
document.addEventListener('keydown', listener);
return () => {
document.removeEventListener('keydown', listener);
}
},[handleConfirm]);
useEffect(()=>{
const listener = (event:{code:string, preventDefault:() => void}) => {
if(event.code === 'Escape'){
handleCancel();
event.preventDefault();
}
}
document.addEventListener('keydown', listener);
return () => {
document.removeEventListener('keydown', listener);
}
},[handleCancel]);
}
2. debounce hook
debounce는 여러번의 요청이 발생하는 경우 모든 요청을 그대로 처리하는 것이 아니라 요청의 마지막에서 특정 시간이 지난 후 하나의 요청만 보내는 것으로 resizing이나 검색어 추천등에 사용된다. 아래 hook은 input의 onChange 등의 이벤트가 있는 경우 어느정도 요청이 을 보낸 후 마지막 요청을 보냈을 때 delay 타임 이후 요청한 값에 대한 처리를 시작한다.
interface IUSerDebounce {
value:any,
delay:number
}
const UseDebounce = ({value, delay}:IUSerDebounce) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(()=>{
const handler = setTimeout(()=>{
setDebouncedValue(value)
}, delay)
return () => {
clearTimeout(handler);
}
}, [value, delay])
return debouncedValue;
}
3. resizing hook
반응형을 width에 따라 구현해야 하는데 라이브러리를 사용하는 것도 좋지만 의존성을 줄이기 위해 아래와 같이 간단하게 custom hook을 작성해서 사용할 수 있다.
import React, { useEffect, useState } from 'react';
const useWindowResize = () => {
const [width, setWidth] = useState(window.innerWidth);
const [height, setHeight] = useState(window.innerHeight);
const listener = () => {
setWidth(window.innerWidth);
setHeight(window.innerHeight);
}
useEffect(()=>{
window.addEventListener(
"resize", listener
)
return () => {
window.removeEventListener("resize", listener)
};
},[])
return {
width,
height
}
}
export default useWindowResize;
혼자 개발을 한다면 모르겠지만 협업을 하는 과정에서 custom hook은 그 사용에 의한 결과를 잘 생각해보고 사용해야겠다는 생각을 하게 된다. 단순히 깔끔해보이려고 사용했다기 보다는 정확히 custom hook을 사용할 수 있는 지점들이 있을 것이라 보인다. 자주 사용해 보면서 최적으로 사용할 수 있는 지점에 대한 감을 익혀봐야겠다.
아래의 내용을 참고했습니다.
https://betterprogramming.pub/react-custom-hooks-with-real-life-examples-c259139c3d71
'React' 카테고리의 다른 글
알았는데 까먹은 React 기록 - useEffect와 componentWillUnmount (0) | 2022.12.26 |
---|---|
React Suspense 적용기 (0) | 2022.12.11 |
react-query 기초 및 적용하기 (0) | 2022.12.07 |
[사용성 개선] Lazy loading with react, typescript (0) | 2022.12.04 |
Redux 기초 (0) | 2022.11.27 |