• 컴포넌트에서 반복되는 로직이 많을 때 custom hooks
을 이용하면 편리
-> 컴포넌트 분할과 달리 컴포넌트 로직 자체를 분할하거나 재사용이 가능
• 보통은 hooks/
디렉토리 안에 커스텀 훅을 정의하여 사용
• use
로 시작하는 파일을 만드는 것이 관례
▶️ 자주 묻는 질문
을 가지고 이해를 해보자
-> 이렇게 hooks/ 디렉토리 안에 custom hook을 생성한다.
hooks/useToggle.js
import React, { useState } from 'react';
//UseToggle 함수를 사용할때 initValue를 사용할수도 사용하지 않을수도 있다. 만약 사용하지 않으면 false반환
export default function useToggle(initValue = false) {
//value : toggle 상태
//setValue : 트글 상태를 변화시키는 setter
const [value, setValue] = useState(initValue);
//토글 상태를 스위칭
const toggleValue = () => {
setValue(!value);
};
return [value, toggleValue]; //반환값이 배열
}
-> 그 다음에 Components/ 디렉토리안에 Faq.js 즉, 커스텀 훅을 사용할 컴포넌트를 생성한다.
Components/Faq.js
//자주 묻는 질문
import React from 'react';
import useToggle from '../hooks/useToggle';
export default function Faq() {
const [isFaqOpen, setIsFaqOpen] = useToggle();
return (
<div>
<h1>custom hook (UseToggle) ex</h1>
<div onClick={setIsFaqOpen} style={{ cursor: 'pointer' }}>
Q. react에서 커스텀 훅을 만들 수 있나요?
</div>
{/* 대답을 누르면 열리는거가 밑에 */}
{isFaqOpen && <div>A. 네 그럼요 가능합니다.</div>}
</div>
);
}
이렇게 간단하게 만들 수 있다.
📌 질문이 여러개 인 경우는 props로 받으면 될까? 하는 의문이 생겼다. 해보자
-> 컴포넌트의 재사용성을 높이기 위해선 props를 활용하면 되니까..
사실 그냥 간단하다. Faq.js
에서 고정된 질문을 props로 빼면 된다.
우선, custom hook으로 작성했던 hooks/useToggle.js
동일하다.
Components/FaqPrac.js
import React from 'react';
import useToggle from '../hooks/useToggle';
//여러개의 질문을 넣을 수 있음
// FAQ 항목을 표시하고 토글하는 컴포넌트
function FaqItem({ question, answer }) {
const [isOpen, toggleOpen] = useToggle(false); // 각 FAQ 항목의 토글 상태를 관리
return (
<div>
<div onClick={toggleOpen} style={{ cursor: 'pointer' }}>
Q. {question}
</div>
{isOpen && <div>A. {answer}</div>}
</div>
);
}
// Faq 컴포넌트는 여러 FAQ 항목을 props로 받는다.
export default function Faq({ faqs }) {
return (
<div>
<h1>Custom Hook (useToggle) Example</h1>
{faqs.map((faq, index) => (
<FaqItem key={index} question={faq.question} answer={faq.answer} />
))}
</div>
);
}
📌 참고 - map 메서드가 key를 써야 하는 이유
map
메서드는 각 배열 요소에 대해 실행할 로직을 정의하고, 그 결과로 새로운 배열을 얻을 수 있기에 동적으로 렌더링할때 매우 유용하다.
근데 이때 key
를 쓰는 것을 매우 권장하는데 그 이유는, 리액트가 어떤 항목이 변경, 추가 또는 삭제되었는지를 식별
하는 데 도움을 주기 때문이다. 이를 통해 리액트는 효율적으로 데이터 변화를 처리하고, 필요한 항목만을 업데이트하여 성능을 최적화할 수 있기에 써야한다!!
src/App.js
import FaqPrac from './Components/FaqPrac';
function App() {
const faqs = [
{
question: 'React에서 커스텀 훅을 만들 수 있나요?',
answer: '네 그럼요 가능합니다.',
},
{
question: 'useEffect 훅은 무엇인가요?',
answer:
'컴포넌트가 렌더링될 때마다 특정 작업을 실행할 수 있게 해주는 Hook입니다.',
},
// 더 많은 FAQ 항목 추가 가능
];
return (
<div className="App">
<FaqPrac faqs={faqs} />
</div>
);
}
export default App;
-> 따로따로 해당 질문에 대한 대답을 확인할 수 있고, 내용은 faqs
안에 추가하면 될 것 같다.