컴포넌트를 만들면 반복되는 로직이 자주 발생하게 된다. 이때 커스텀 Hooks 를 만들어서 반복되는 로직을 정의한 후 간편하게 호출함으로써 쉽게 재사용할 수 있다.
주로 use
라는 키워드로 시작하는 파일을 만들고 안에 함수를 작성해서 사용한다.
useState
, useEffect
, useReducer
, useCallback
등 Hooks를 사용해서 원하는 기능을 구현하고 컴포넌트에서 사용하고 싶은 값들을 반환해주면 된다.
변경사항이 있을 씨 커스텀 훅에서만 변경하면 되므로 수정하기에 효율적이다.
커스텀 훅을 작성할 때는 항상 use로 시작한다.
📌 Hook의 특징
훅 또는 함수 컴포넌트 안에서만 실행이 가능하다. 즉 훅 안에 다른 훅을 사용할 수 있다.
✍️ 여러개의 Input 관리하기
기본적인 입력 폼
import React, { useState, useCallback } from 'react';
// state
const [text, setText] = useState({
id: '',
pw: '',
});
// func
const onChange = useCallback(
(e) => {
const { value, name } = e.target;
setText({ ...text, [name]: value });
},
[text]
);
return (
<>
<input id='id' value={text.id} onChange={onChange} />
<input id='pw' value={text.pw} onChange={onChange} />
</>
);
✍️ 훅 반영하기
import { useState, useCallback } from 'react';
export default (initalValue = null) => {
// state
const [data, setData] = useState(initalValue);
// func
const handler = useCallback(
(e) => {
const { value, name } = e.target;
setData({
...data,
[name]: value,
});
},
[data]
);
return [data, handler];
};
// 반영한 로직
import UseInput from './UseInput';
const [text, setText] = useInput({
id: '',
pw: '',
});
return (
<>
<input id='id' value={text.id} onChange={onChange} />
<input id='pw' value={text.pw} onChange={onChange} />
</>
);
useInput
훅 안에 useState와 useCallback에 있는 함수를 미리 정의했으므로 컴포넌트에서는 훅을 사용하기만 하면 된다.✍️ useFetch 만들어서 사용하기
// useFetch.tsx
import {useEffect, useState} from 'react';
import {getToken} from 'AuthContext';
const useFetch = (url: string) => {
const [fetchData, setFetchData] = useState({});
useEffect(() => {
if (!url) {
return;
}
const getFatchData = async (url: string) => {
const token = await getToken();
const getData = await fetch(url, {
method: 'GET',
headers: {
Authorization: token,
},
});
const res = await getData.json();
setFetchData(res);
};
getFatchData(url);
}, [url]);
return fetchData;
};
export default useFetch;
// AuthContext.tsx의 getToken
export const getToken = async () => {
try {
const token = await AsyncStorage.getItem('access_token');
return String(token);
} catch (error) {
throw new Error('token 저장 실패');
}
};
✍️ 훅 반영하기 (react-native)
// config.ts
export const BASE_URL = '...';
const API = {
departmentList: `${BASE_URL}/appointments/departments`,
...
};
export default API;
// MainHome
import useFetch from 'components/useFetch';
const MainHome = ({navigation}: MainHomeScreenProps) => {
const departmentListUrl = `${API.departmentList}`;
const departmentListData = useFetch(departmentListUrl).result;
return (
...
<View>
<FlatList
data={departmentListData} // 받아온 데이터를 넣어준다.
columnWrapperStyle={{
justifyContent: 'space-between',
marginBottom: 55,
}}
renderItem={({item}) => (
<Pressable
style={[
styles.alignStyle,
styles.iconBox,
{width: width / 5, height: width / 5},
]}
onPress={() => {
navigation.navigate('DocList', item);
}}>
<Image
source={{
uri: item.thumbnails,
}}
style={styles.iconImg}
/>
<Text style={[styles.iconTitle, styles.nameText]}>
{item.name.replace(' ', `${'\n'}`)}
</Text>
</Pressable>
)}
keyExtractor={item => item.id.toString()}
numColumns={3}
/>
...
);
};
reference)
customHooks