headless ui란, 컴포넌트 라이브러리로, UI 로직만 제공하고 스타일이나 디자인은 포함하지 않는 라이브러리다.
Ant design과 같은 컴포넌트 라이브러리와의 차이점은 특정 디자인을 강제하지 않고, 디자인을 사용자 맘대로 지정할 수 있다는 점이 장점이 있다.
headless-ui와 비슷한 라이브러리로는 radix-ui가 있다.
더 나아가, 이를 활용해서 또 새로운 형태의 라이브러리를 제공하는 shadcn 같은 라이브러리도 있는데,,
shadcn은 radix-ui에 디자인 입힌 버전..? 일종의 Tailwind CSS 기반의 Radix UI 래퍼..(?)라고 생각하면 된다.
사실 headless-ui를 사용하면서 다양한 이슈들을 경험하고 있다.
얼마 전에는 라이브러리에서 활용하는 라이브러리의 이슈(@tanstack/virtual) 때문에 발생하는 이슈가 있는데, 해결했다고 관련 issue가 PR 언급하며 closed 됐는데,, 아직 같은 이슈가 발생중이다... 🤔
(궁금하신 분들을 위해서.. 이 이슈다.. 아직도 빈배열 들어가면 오류난다! 그래서 일단 이러한 형태['']
를 넣는 방식으로 해결했다. )
조만간 조금 더 제대로 파보고 내가 issue 올려볼까 생각중이다.
disclosure가 open인 경우에만, validation을 진행하고 close인 경우에는 validation을 하지 않는다.
근데 disclosure에 대한 onChange가 존재하지 않아서 어떻게 구현해야할지 고민을 열심히 해보았다!
그래서 순차적으로 다음과 같은 해결법들을 생각해냈다.
작동은 하지만, 렌더링 문제 때문에 에러가 발생했다.
이거는 딱 봐도 좋은 방법은 아니다... ㅋㅋㅋ...
disclosure를 활용하지 않고 그 외적인 방법으로 해결하는 방법을 생각해봤다.
disclosure 내부에 토글을 하나 더 추가해서.. 그걸 키고 닫을 때, validation의 여부를 키고 끄고를 하고자 했다. 이거 관련해서 30분 이상 시간을 쓰고 있자, 비효율적임을 깨닫고 생각해본 방법이다.
근데 해당 방식 사용시,
오히려 이게 더 시간이 많이 걸리고 코드가 더러워질 것 같다는 판단 하에 disclosure를 활용해서 해결하자는 결론에 이르렀다..!
그래서 해결책에 도달한 과정은 다음과 같다.
const Button = forwardRef<HTMLButtonElement, any>(function (props, ref) {
const { onClick, ...rest } = props;
const { setValue, resetField } = useFormContext<CampaignView>();
const [open, setOpen] = useState(false);
return (
<button
ref={ref}
{...rest}
onClick={(e) => {
handleDisclosureButtonClick();
onClick?.(e);
}}
/>
);
function handleDisclosureButtonClick() {
if (open) {
setOpen(false);
resetField('name');
} else {
setOpen(true);
setValue('name', initial_value);
}
}
});
이렇게 해서
function Example() {
return (
<Disclosure>
<DisclosureButton>Open mobile menu</DisclosureButton>
<DisclosurePanel>
<CloseButton as={Button} href="/home">
Home
</CloseButton>
</DisclosurePanel>
</Disclosure>
)
}
as={Button}
과 같이 넣어주면 된다~!
https://github.com/tailwindlabs/headlessui/discussions/640
해당 논의를 보면, children으로 button 컴포넌트를 따로 추가해줘도 되는 것 같다!
나는 공통 컴포넌트로 만들어서 사용하기 때문에 불필요한 곳들도 존재하기 때문에 내가 생각해낸 방식이 더 적합한 것 같다. 다만, 상황에 따라서 위의 논의에서 언급한 방식이 코드가 간결해질 것 같기도 하니 참고하시라!