이글은 아래 링크를 번역한 글입니다.
원문은 여기(영문)
상위구성요소와 하위구성요소 간의 통신에 후크를 사용해보자. 예로 하위구성요소에 Accordion을 포함하는 상위구성요소 Home이 있다고 하자.
요구사항은,
1. Home에서는 Accordion을에 대한 Label과 하위항목을 설정해야 한다.
2. Accordion은 홈에 상태(펼치기/닫기)를 알려야 한다.
첫 번째 요구사항은 구현하기 쉽다. 아래코드처럼 Home은 Props를 Accordion에 전달할 수 있어야 한다.
// accordion.types.ts
export type AccordionProps = {
label: string
children: ReactNode
}
// accordion.tsx
export const Accordion = ({ label, children }: AccordionProps) => {
return (
<div>
<p>{label}</p>
{children}
</div>
)
}
// home.tsx
export const Home = () => {
return (
<div>
<Accordion label="Accordion label">
<div>Accordion content</div>
</Accordion>
</div>
)
})
두 번째 요구사항을 좀더 구체화해서 Accordion을 아래 기능을 추가해 내부상태로 expended
를 가지고 toggle
내부기능이 있다고 하자.
여기서 Hook를 사용한다. Accordion을 논리를 집중화하기 위해 useAccordion
즉 커스텀후크를 작성한다.
// accordion.hook.tsx
export const useAccordion = () => {
const [expanded, setExpanded] = useState(false)
const toggle = () => setExpanded((x) => !x)
return { expanded, toggle }
}
// accordion.tsx
export const Accordion = ({ label, children }: AccordionProps) => {
const { expanded, toggle } = useAccordion()
return (
<div onClick={toggle}>
<p>{label}</p>
{expanded && children}
</div>
)
}
이제 아코디언도 작동하게 되었다. 하지만 Accordion은 Home에 내부상태를 어떻게 알릴 수 있을까?
아마도 가장 먼저 떠오르는 아이디어는 Accordion props에 onChange
콜백을 추가하여 Home이 알림을 받는 함수를 전달할 수 있도록 하는 것이다.
이 방법은 나름 괜찮지만 다음과 같은 두 가지 이유로 인해 번거롭다.
여기서 제대로 Hook을 활용하려면 아래와 같이 Hook에서 반환된 모든것을 props로 받아들이는 것이다.
// accordion.types.ts
export type AccordionProps = ReturnType<typeof useAccordion> & {
label: string
children: ReactNode
expanded: boolean;
toggle: () => void;
}
// accordion.tsx
import React from 'react';
import { AccordionProps } from './accordion.types';
export const Accordion = ({
label,
children,
expanded,
toggle
}: AccordionProps) => {
return (
<div onClick={toggle}>
<p>{label}</p>
{expanded && children}
</div>
);
};
// home.tsx
import React from 'react';
import { Accordion } from './accordion';
import { useAccordion } from './useAccordion'; // Assuming you have this hook
export const Home = () => {
const { expanded, toggle } = useAccordion();
return (
<div>
<p>Accordion state: {expanded ? 'Expanded' : 'Collapsed'}</p>
<Accordion label="Accordion label" expanded={expanded} toggle={toggle}>
<div>Accordion content</div>
</Accordion>
</div>
);
};
useAccordion()
의 결과는 Accordion props로 이동되었다.
그리고 Home은 Accordion내부상태에 접근하거나 또는 내부함수에 invoke/override를 하려면 아래와 같다.
// home.tsx
export const Home = () => {
const { expanded, toggle } = useAccordion()
const customToggle = () => {
// Override here
toggle() // Invoke here
}
return (
<div>
<p>Accordion state: {expanded}</p>
<Accordion
label="Accordion label"
expanded={expanded}
toggle={customToggle}
>
<div>Accordion content</div>
</Accordion>
</div>
)
})
Home에서 toggle
기능을 호출하고 재정의할 수 있다는 사실은 정말 강력한 기능이다.
요약하면 후크 디자인 패턴은 다음과 같은 장점이 있다.