매일매일
Published 2023. 3. 27. 21:51
Custom Hook React

1. useFetch

fetch 할 때 반복되는 코드를 커스텀 훅으로 만들어 활용할 수 있다.

<javascript />
import { useState, useEffect } from 'react'; const useFetch = (url) => { const [data, setData] = useState(null); const [isPending, setIsPending] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(url, { // get의 경우 헤더를 작성하지 않아도 괜찮 headers: { "Content-Type" : "application/json", Accept: "application/json" } }) .then(res => { if (!res.ok) { throw Error('could not fetch the data for that resource'); } return res.json(); }) .then(data => { setIsPending(false); setData(data); setError(null); }) .catch(err => { setIsPending(false); setError(err.message); }) }, [url]) // url에 영향받으므로 종속배열에 url // 리턴은 값으로 return [data, isPending, error]; } export default useFetch;

커스텀훅으로 만들어 두면 필요할 때 마다 위의 코드를 전체를 다시 반복할 필요 없이 아래와 같이 활용하면 된다.

<javascript />
const [blog, isPending, error] = useFetch(`http://localhost:3001/blogs/${id}`)

 아니면 api를 문서화 하여 활용할 수도 있다. (헤더는 꼭 작성해주기 안 하니깐 데이터가 날아갔다...)

<javascript />
const BASE_URL = 'http://localhost:3000/'; const BLOG_URL = 'http://localhost:3000/blogs/'; // post: 새 데이터 추가(id는 자동 추가됨) export const fetchCreate = (url, data) => { fetch(url, { method: "POST", headers: { "Content-Type" : "application/json", Accept: "application/json" }, body: JSON.stringify(data) }) .then(() => { window.location.href = BASE_URL; // 특정 URL로 접속했을 때 다른 URL로 이동시킴(3000으로 이동) }) .catch((error) => { console.error('Error', error); }) } // delete: 데이터 삭제(get과 마찬가지로 헤더 필수 아님) export const fetchDelete = (url, id) => { fetch(`${url}${id}`, { method: "DELETE", }) .then(() => { window.location.href = BASE_URL; }) .catch((error) => { console.error('Error', error); }) } // patch 기존 데이터 수정 export const fetchPatch = (url, id, data) => { fetch(`${url}${id}`, { method : "PATCH", headers: { "Content-Type" : "application/json", Accept: "application/json" }, body: JSON.stringify(data) }) .then(() => { window.location.href = `${BLOG_URL}${id}`; }) .catch((error) => { console.error('Error', error); }) }

 

2. useInput

input 사용 시 상태 변경 로직을 컴스텀 훅으로 만들 수 있다.

<javascript />
import { useCallback, useState } from "react"; const useInput = () => { // input 값에 대한 상태 const [value, setValue] = useState(''); // 값과 값 변경 시 상태변경 함수 객체로 묶음 const bind = { value, onChange : useCallback((e) => { const { value } = e.target; setValue(value) }, []) } return bind; } export default useInput;

상태변경 함수를 useCallback으로 감싸주면 input에 입력할 때마다 새로운 함수가 생성되는 것이 아니라 기존의 함수를 재활용할 수 있다. useCallback의 종속배열이 []인 이유는 useCallback이 의존하는 변수 없기  때문이다.

 

Input을 컴포넌트로 만든다면 좀 더 코드를 정리할 수 있다.

<javascript />
//textarea도 multi-line input이므로 input 이름으로 범용성을 주는 게 좋음. //혹시 헷갈릴 수 있다면 그냥 따로 component를 이 안에 만들어줘도 무방하다. const Input = ({label, value}) => { //따로 컴포넌트를 만드는 경우 const inputComponent = <> <input type="text" required {...value} placeholder={`${label}을 입력해주세요.`} /> </> const textAreaComponent = <> <textarea type="text" required {...value} placeholder={`${label}을 입력해주세요.`} /> </> return ( <> <label>{label}</label> {label === "제목" ? <input type="text" required {...value} // useInput에서 값과 onchange를 객체로 묶어줬으므로 스프레드로 속성 입력 가능 placeholder={`${label}을 입력해주세요.`} /> : <textarea type="text" required {...value} placeholder={`${label}을 입력해주세요.`} /> } {/* 따로 만드는 경우 */} {/* <label>{label}</label> { label === "제목" ? inputComponent : textAreaComponent } */} </> ) } export default Input;
 

 

useInput에서 값과 onchange를 객체로 묶어줬으므로 스프레드 문법을 활용 하면 input 속성 입력 시 좀 더 간편하게 작성할 수 있다. value={value}, onchange={e=>...} 가 리턴 값이므로 스프레드 문법으로 풀어서 사용 가능하다. 예를 들어

<javascript />
const CreateBlog = ({blogs}) => { const titleBind = useInput(''); const bodyBind = useInput(''); const authorBind = useInput('김코딩'); return ( <Input label={"제목"} value={titleBind} /> <Input label={"내용"} value={bodyBind} /> ) }

 

3. useScrollTop

적용된 컴포넌트 진입시 페이지 맨 위로 스크롤해주는 커스텀 훅
App 컴포넌트에서 실행해주기
<javascript />
import { useEffect } from 'react'; // 적용된 컴포넌트 진입시 페이지 맨 위로 스크롤해주는 커스텀 훅 const useScrollTop = () => { // 처음 렌더링 시 맨 위로 스크롤 이동 useEffect(() => { if (window) window.scrollTo(0, 0); }, []) } export default useScrollTop;

'React' 카테고리의 다른 글

Redux Thunk 미들웨어 사용해보기  (0) 2023.04.11
to do 앱 만들기 후기  (0) 2023.04.09
리액트로 달력만들기  (0) 2023.04.08
Proxy  (0) 2023.04.04