bkdragon's log

children 을 함수해서 동적으로 스타일을 지정하기 본문

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>

이렇게 사용할 수 있다.