[React] Custom Hooks
리액트에서는 내가 원하는 인터페이스, 기능을 담은 나만의 커스텀훅을 직접 만들 수 있다.
커스텀 훅을 만들어두면 다른 리액트 훅처럼 필요할 때마다 간단히 불러와서 사용할 수 있다.
Custom hook이란?
Custom hook이란 우리의 입맛데로 직접 커스텀해서 만든 리액트 훅이다.
커스텀 훅을 만드는 방법은 간단한다.
// Custom Hook
function useEat(){ // 원하는 이름
//...원하는 기능을 함수안에 구현
}
컴포넌트 내부에 있는 로직을 커스텀훅이라는 함수 속으로 빼주는 것이다.
물론 매개변수, 리턴값도 마음대로 정할 수 있다.
커스텀 훅이 매력적인 이유는 커스텀훅 내부 안에 리액트 훅들을 자유롭게 사용 가능하면
커스텀 훅을 사용하는 컴포넌트마다 커스텀 훅이 가지고 있는 state, effect는 완전히 다른 독립적이기 때문에
커스텀 훅은 폭발적인 재사용성을 제공한다.
useInput 커스텀 훅 만들기
const Custom1 = () => {
const [inputValue, setInputValue] = useState("");
const handleChange = (e) => {
setInputValue(e.target.value);
};
const handleSubmit = () => {
alert(inputValue);
setInputValue("");
};
return (
<div>
<h1>useInput</h1>
<input value={inputValue} onChange={handleChange} />
<button onClick={handleSubmit}>확인</button>
</div>
);
};
input을 처리하는 기능을 담은 커스텀 훅 만들기
커스텀 훅을 만든다는 것은 함수를 하나 만드는 것이다.
useInput은 우리가 만들 커스텀 훅이다. (input 기능을 처리할 훅)
함수 이름은 마음데로 지어도 되지만 커스텀 훅도 리액트 훅이기 때문에 use라는 키워드로 시작해야 된다.
그래야지만 훅을 사용하면서 이상한 실수를 저지를 때마다 리액트 자체에서 콘솔에 적절한 경고 메시지를 띄우기 때문이다.
커스텀훅 안에다가 useState와 같은 리액트 훅들을 자유롭게 사용할 수 있다.
useInput 커스텀 훅
// useInput.js
import { useState } from "react";
export function useInput(initialValue) {
const [inputValue, setInputValue] = useState(initialValue);
const handleChange = (e) => {
setInputValue(e.target.value);
};
return [inputValue, handleChange];
}
useInput커스텀 훅 사용하기
const Custom1 = () => {
const [inputValue, handleChange] = useInput("안녕");
const handleSubmit = () => {
alert(inputValue);
// setInputValue("");
};
return (
<div>
<h1>useInput</h1>
<input value={inputValue} onChange={handleChange} />
<button onClick={handleSubmit}>확인</button>
</div>
);
};
원하는 만큼 사용해 줄 수 있다.
const Custom1 = () => {
const [inputValue, handleChange] = useInput("안녕");
const [inputValue2, handleChange2] = useInput("123");
const handleSubmit = () => {
alert(inputValue);
// setInputValue("");
};
return (
<div>
<h1>useInput</h1>
<input value={inputValue} onChange={handleChange} />
<input value={inputValue2} onChange={handleChange2} />
<button onClick={handleSubmit}>확인</button>
</div>
);
};
인풋처리도 각각 할 수 있다.
만약 컴포넌트들이 많고 컴포넌트 하나하나마다 input처리를 해줘야 된다면
지금 만든 useInput 커스텀 훅을 가져다가 한 줄만 추가하면 끝난다.
const [inputValue2, handleChange2] = useInput("123");
handleSubmit도 useInput에 추가하기
// useInput 커스텀 훅
import { useState } from "react";
export function useInput(initialValue, submitAction) {
const [inputValue, setInputValue] = useState(initialValue);
const handleChange = (e) => {
setInputValue(e.target.value);
};
const handleSubmit = () => {
setInputValue("");
submitAction(inputValue);
};
return [inputValue, handleChange, handleSubmit];
}
function displayMessage(message) {
alert(message);
}
const Custom1 = () => {
const [inputValue, handleChange, handleSubmit] = useInput(
"",
displayMessage
);
return (
<div>
<h1>useInput</h1>
<input value={inputValue} onChange={handleChange} />
<button onClick={handleSubmit}>확인</button>
</div>
);
};
커스텀 훅의 재사용성이 좋은 이유는 커스텀 훅이 가지고 있는 state와 effect는 커스텀 훅을 사용하는 컴포넌트마다 독립적이기 때문이다.
한 컴포넌트에 커스텀훅을 여러 개 사용해도 독립적인 effect가 여러개 생성
그래서 input 여러 개 처리하기 위해 useInput 커스텀 훅을 반복해서 사용해도 각각의 input은 독립적인 state를 가질 수 있는 것이다.
useFetch 커스텀 훅 만들기
fetch API를 통해 네트워크에서 데이터를 가져오는 기능을 해주는 커스텀 훅
const baseUrl = "https://jsonplaceholder.typicode.com";
const Custom2 = (type) => {
const [data, setData] = useState(null);
const fetchUrl = (type) => {
fetch(baseUrl + "/" + type)
.then((res) => res.json())
.then((res) => setData(res));
};
useEffect(() => {
fetchUrl("users");
}, []);
console.log(data);
return (
<div>
<h1>useFetch</h1>
<button onClick={() => fetchUrl("users")}>Users</button>
<button onClick={() => fetchUrl("posts")}>Posts</button>
<button onClick={() => fetchUrl("todos")}>Todos</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
useFetch 커스텀 훅 만들기
useFetch 커스텀 훅
// useFetch 커스텀 훅
import { useEffect, useState } from "react";
export function useFetch(baseUrl, initalType) {
const [data, setData] = useState(null);
const fetchUrl = (type) => {
fetch(baseUrl + "/" + type)
.then((res) => res.json())
.then((res) => setData(res));
};
useEffect(() => {
fetchUrl(initalType);
}, []);
return {
data,
fetchUrl,
};
}
const baseUrl = "https://jsonplaceholder.typicode.com";
const Custom2 = () => {
const { data, fetchUrl } = useFetch(baseUrl, "users");
return (
<div>
<h1>useFetch</h1>
<button onClick={() => fetchUrl("users")}>Users</button>
<button onClick={() => fetchUrl("posts")}>Posts</button>
<button onClick={() => fetchUrl("todos")}>Todos</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
조금 더 응용하기 1
const baseUrl = "https://jsonplaceholder.typicode.com";
const Custom2 = () => {
const { data: userData } = useFetch(baseUrl, "users");
return (
<div>
<h1>useFetch</h1>
{userData && <pre>{JSON.stringify(userData[0], null, 2)}</pre>}
</div>
);
};
조금 더 응용하기 2
const baseUrl = "https://jsonplaceholder.typicode.com";
const Custom2 = () => {
const { data: userData } = useFetch(baseUrl, "users");
const { data: postData } = useFetch(baseUrl, "posts");
return (
<div>
<h1>User</h1>
{userData && <pre>{JSON.stringify(userData[0], null, 2)}</pre>}
<h1>Post</h1>
{postData && <pre>{JSON.stringify(postData[0], null, 2)}</pre>}
</div>
);
};
※ 이 글은 별코딩 리액트 훅 강의를 보고 정리한 글입니다.