Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 자바스크립트#JS#var#let#const#undefined#null
- variable#function
- redux상태유지
- https://dasima.xyz/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%A0%9C%EA%B3%B1-math-pow-%EA%B3%84%EC%82%B0/
- UX
- 헷갈린다~
- Beesbeesbees
- slice/splice/split
- children vs childrenNodes
- https://www.daleseo.com/js-array-slice-splice/
- 자바스크립트#JS#slice#splice
- dom
- cmarket
- 내장고차함수
- https://developer-talk.tistory.com/299
- CSS
- 자바스크립트
- ㄷㅌ
- JS#3일차달리자#초반인데#시간금방~
- js
- UI
- 자바스크립트#조건문#문자열
- @redux-toolkit
- toString#String
- removeCookie
- react
- https://lo-victoria.com/introduction-to-redux-toolkit-for-beginners
- User Flow
- for~in/for~of
- 노드교과서
Archives
- Today
- Total
Daily Front_Minhhk
Custom Hooks 본문
개발자가 스스로 커스텀한 훅을 의미하며 이를 이용해 반복되는 로직을 함수로 뽑아내어 재사용할 수 있습니다.
여러 url을 fetch할 때, 여러 input에 의한 상태 변경 등 반복되는 로직을 동일한 함수에서 작동하게 하고 싶을 때 커스텀 훅을 주로 사용합니다. 이를 이용하면
- 상태관리 로직의 재활용이 가능하고
- 클래스 컴포넌트보다 적은 양의 코드로 동일한 로직을 구현할 수 있으며
- 함수형으로 작성하기 때문에 보다 명료하다는 장점이 있습니다.
예시를 살펴보자!!
//FriendStatus : 친구가 online인지 offline인지 return하는 컴포넌트
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
//FriendListItem : 친구가 online일 때 초록색으로 표시하는 컴포넌트
function FriendListItem(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
FriendStatus 컴포넌트는 사용자들이 온라인인지 오프라인인지 확인하고, FriendListItem 컴포넌트는 사용자들의 상태에 따라 온라인이라면 초록색으로 표시하는 컴포넌트입니다.
이 두 컴포넌트는 정확하게 똑같이 쓰이는 로직이 존재하고 있습니다. 이 로직을 빼내서 두 컴포넌트에서 공유할 수는 없을까요? Custom Hook을 사용한다면 가능합니다
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
이렇게 Custom Hook을 정의할 때는 일종의 규칙이 필요합니다.
- Custom Hook을 정의할 때는 함수 이름 앞에 use를 붙이는 것이 규칙입니다.
- 대개의 경우 프로젝트 내의 hooks 디렉토리에 Custom Hook을 위치 시킵니다.
- Custom Hook으로 만들 때 함수는 조건부 함수가 아니어야 합니다. 즉 return 하는 값은 조건부여서는 안 됩니다.
Custom Hook 이용
위에서 추출한 Custom Hook을 적용하면, 아래와 같이 작성할 수 있다.
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
단, 같은 Custom Hook을 사용했다고 하더라도 두 컴포넌트는 같은 로직만 공유할 뿐, state는 컴포넌트 내에서 독립적으로 정의되어 있으므로 같은 state를 공유하는 것은 아니다.
또 다른 예시🐤
const useFetch = ( initialUrl:string ) => {
const [url, setUrl] = useState(initialUrl);
const [value, setValue] = useState('');
const fetchData = () => axios.get(url).then(({data}) => setValue(data));
useEffect(() => {
fetchData();
},[url]);
return [value];
};
export default useFetch;
[코드] 여러 url을 fetch할 때 쓸 수 있는 useFetch Hook
import { useState, useCallback } from 'react';
function useInputs(initialForm) {
const [form, setForm] = useState(initialForm);
// change
const onChange = useCallback(e => {
const { name, value } = e.target;
setForm(form => ({ ...form, [name]: value }));
}, []);
const reset = useCallback(() => setForm(initialForm), [initialForm]);
return [form, onChange, reset];
}
export default useInputs;
[코드] 여러 input에 의한 상태 변경을 할 때 쓸 수 있는 useInputs Hooks
🐤실습
useFetch() 실습
App.js
import "./styles.css";
import useFetch from "./util/useFetch"
// import datas from "../public/data.json"
export default function App() {
const fetchData = useFetch("data.json");
return (
<div className="App">
<h1>To do List</h1>
<div className="todo-list">
{/* fetchData 가 있을때 값을 받아 오겠다 */}
{fetchData &&
fetchData.todo.map((el) => {
return <li key={el.id}>{el.todo}</li>;
})}
</div>
</div>
);
}
src/util/useFetch.js
//app.js에서 함수를 가져와서 Custom hook을 만들어 봅시다.
//hooks.js의 이름도 알맞게 바꿔주세요.
import { useEffect, useState } from "react";
const useFetch = (fetchUrl) => {
const [data, setData] = useState();
useEffect(() => {
fetch(fetchUrl, {
headers: {
"Content-Type": "application/json",
Accept: "application/json"
}
})
.then((response) => {
return response.json();
})
.then((myJson) => {
setData(myJson);
})
.catch((error) => {
console.log(error);
});
}, [fetchUrl]);
return data;
};
export default useFetch;
useInput() 실습
src/component/Input.js
function Input({ label, value }) {
return (
<div className="name-input">
<label>{label}</label>
<input {...value} type="text" />
</div>
);
}
export default Input;
src/util/useInput.js
import { useState } from "react";
function useInput(initialValue) {
const [value, setValue] = useState(initialValue);
const bind = {
value,
onChange: (e) => {
setValue(e.target.value);
}
};
// 제출 후 인풋 값 리셋
const reset = () => {
setValue('')
}
return [value, bind, reset];
}
export default useInput;
App.js
import { useState } from "react";
import useInput from "./util/useInput";
import Input from "./component/Input";
import "./styles.css";
export default function App() {
//input에 들어가는 상태값 및 로직을 custom hook으로 만들어봅니다.
//until 폴더의 useInput.js 파일이 만들어져 있습니다.
const [firstNameValue, setFirstNameValue, firstReset] = useInput("first");
const [lastNameValue, setLastNameValue, secondReset] = useInput("last");
const [nameArr, setNameArr] = useState([]);
const handleSubmit = (e) => {
e.preventDefault();
setNameArr([...nameArr, `${firstNameValue} ${lastNameValue}`]);
firstReset()
secondReset()
};
return (
<div className="App">
<h1>Name List</h1>
<div className="name-form">
<form onSubmit={handleSubmit}>
<Input label={"성"} value={setFirstNameValue} />
<Input label={"이름"} value={setLastNameValue} />
<button>제출</button>
</form>
</div>
<div className="name-list-wrap">
<div className="name-list">
{nameArr.map((el, idx) => {
return <p key={idx}>{el}</p>;
})}
</div>
</div>
</div>
);
}
'Code개발일지' 카테고리의 다른 글
컴퓨터 공학 - 구조, 운영체제 (0) | 2023.01.27 |
---|---|
React.lazy()와 Suspense (0) | 2023.01.26 |
Hooks & useMemo, useCallback (1) | 2023.01.25 |
번들링과 웹팩 (0) | 2023.01.18 |
반응형 웹 (0) | 2023.01.16 |