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 |