import { createContext, useContext, useState } from "react";
import AccordionItem from "./AccordionItem";
import AccordionTitle from "./AccordionTitle";
import AccordionContent from "./AccordionContent";
export const AccordionContext = createContext();
export function useAccordionContext() {
const ctx = useContext(AccordionContext);
if (!ctx) {
throw new Error(
"Accordion compound components cannot be rendered outside the Accordion component"
);
}
return ctx;
}
export default function Accordion({ children, className }) {
const [openItemId, setOpenItemId] = useState(null);
function toggleItem(id) {
console.log("Toggling item:", id);
setOpenItemId((prevId) => (prevId === id ? null : id));
}
const contextValue = {
openItemId,
toggleItem,
};
return (
<AccordionContext.Provider value={contextValue}>
<ul className={className}>{children}</ul>
</AccordionContext.Provider>
);
}
Accordion.Item = AccordionItem;
Accordion.Title = AccordionTitle;
Accordion.Content = AccordionContent;
import { createContext, useContext } from "react";
const AccordionIdContext = createContext();
export function useAccordionId() {
const context = useContext(AccordionIdContext);
if (!context) {
throw new Error("AccordionItem must be used within an AccordionItem");
}
return context;
}
export default function AccordionItem({ id, children, className }) {
return (
<li className={className}>
<AccordionIdContext.Provider value={{ id }}>
{children}
</AccordionIdContext.Provider>
</li>
);
}
import { useAccordionContext } from "./Accordion";
import { useAccordionId } from "./AccordionItem";
export default function AccordionTitle({ children, className }) {
const { toggleItem } = useAccordionContext();
const { id } = useAccordionId();
return (
<h3 className={className} onClick={() => toggleItem(id)}>
{children}
</h3>
);
}
import { useAccordionContext } from "./Accordion";
import { useAccordionId } from "./AccordionItem";
export default function AccordionContent({ children, className }) {
const { openItemId } = useAccordionContext();
const { id } = useAccordionId();
const isOpen = openItemId === id;
return (
<div
className={
isOpen ? `${className ?? ""} open` : `${className ?? ""} close`
}
>
{children}
</div>
);
}
꼭 붙어다니는 것들 주로 사용
1. 관련 컴포넌트 들을 논리적으로 그룹화
2. 컴포넌트 사용 시 더 명확한 구조 제공
3. 네임스페이스를 통해 이름 충돌을 방지
'개발 > 기록' 카테고리의 다른 글
| 브랜치, 풀 리퀘스트, 이슈 연동 관리 가이드 (1) | 2024.10.22 |
|---|---|
| Render Props Pattern, 동적 props 처리, 디바운싱 (1) | 2024.10.21 |
| React Router의 action과 loader 사용해서 에러 메시지 전달하고 표시하기 (1) | 2024.10.21 |
| React에서 로딩 상태 관리: useNavigation vs useIsFetching (2) | 2024.10.19 |
| 서명과 암호화, 그리고 공개키 방식과 비밀키 방식 (1) | 2024.10.12 |