React
children 을 함수해서 동적으로 스타일을 지정하기
bkdragon
2024. 11. 14. 22:18
이전에 작성한 글 중에 '합성 컴포넌트 패턴과 React Children API 를 활용한 컴포넌트 설계' 라는 글이 있다.
그 글에서 Tab.Item 을 변경해보자.
const Item: FC<{ children: React.ReactNode; index?: number }> = ({ children, index }) => {
const { activeTab, setActiveTab } = useContext(TabContext);
if (index === undefined) {
throw new Error("index is required");
}
return (
<button className={clsx(activeTab === index && "text-blue-600")} onClick={() => setActiveTab(index)}>
{children}
</button>
);
};
이전 글에선 원래 이렇게 내부에서 스타일을 지정하는데 children을 함수로 만들어서 activeTab 인자로 넘겨서 이 컴포넌트를 사용하는 곳에서 동적으로 스타일링을 할 수 있게 해보자.
const Item: FC<{
children: React.ReactNode | ((props: { hover: boolean; active: boolean }) => React.ReactNode);
index?: number;
}> = ({ children, index }) => {
const { activeTab, setActiveTab } = useContext(TabContext);
const [hover, setHover] = useState(false);
if (index === undefined) {
throw new Error("index is required");
}
return (
<>
<button
onClick={() => setActiveTab(index)}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
>
{typeof children === "function" ? children({ hover, active: activeTab === index }) : children}
</button>
</>
);
};
hover도 추가해서 함수의 인자로 넘긴다.
<Tab.Item>
{({ hover, active }) => (
<div
className={clsx(
"bu-py-2 bu-px-4 bu-flex bu-flex-row bu-justify-center bu-items-center bu-border-b-4 bu-text-sm",
active ? " bu-border-fill-green-500" : "bu-border-app-bg-200",
hover ? "bu-bg-gray-100" : "bu-bg-white"
)}
>
Tab 1
</div>
)}
</Tab.Item>
이렇게 사용할 수 있다.