슬롯

슬롯 (Slot)

자신의 props를 바로 아래에 있는 자식(child)에 병합해 주는 컴포넌트예요. 직접적인 자식 요소가 하나일 때 그 요소에 props와 ref를 전달하는 역할을 해요.

출처: 문서

본문

Slot은 자신의 props를 바로 아래에 있는 자식(child)에 병합해 주는 컴포넌트예요.

기능 (Features)

  • 나만의 asChild prop을 지원하는 데 사용할 수 있어요.

구조 (Anatomy)

컴포넌트를 임포트해요.

import { Slot } from "radix-ui";

export default () => (
  <Slot.Root>
    <div>Hello</div>
  </Slot.Root>
);

기본 예제 (Basic example)

나만의 asChild API를 만들 때 사용해요.

컴포넌트에 자식 요소가 하나뿐일 때:

// your-button.jsx

import * as React from "react";

import { Slot } from "radix-ui";

function Button({ asChild, ...props }) {
  const Comp = asChild ? Slot.Root : "button";

  return <Comp {...props} />;
}

컴포넌트에 자식이 여러 개라서 props를 올바른 요소에 전달해야 한다면 Slottable을 사용해요:

// your-button.jsx

import * as React from "react";

import { Slot } from "radix-ui";

function Button({ asChild, children, leftElement, rightElement, ...props }) {
  const Comp = asChild ? Slot.Root : "button";

  return (
    <Comp {...props}>
      {leftElement}

      <Slot.Slottable>{children}</Slot.Slottable>

      {rightElement}
    </Comp>
  );
}

슬롯된 요소 감싸기 (Wrapping the slotted element)

child prop을 통해 자식을 Slottable에 전달하고 렌더 함수를 제공하면 슬롯된 요소를 추가 마크업으로 감쌀 수 있어요. 이때도 Slot은 여전히 자신의 props와 refs를 자식에 병합해요.

// your-button.jsx

import * as React from "react";

import { Slot } from "radix-ui";

function Button({ asChild, children, ...props }) {
  const Comp = asChild ? Slot.Root : "button";

  return (
    <Comp {...props}>
      <Slot.Slottable child={children}>
        {(child) => <span className="ButtonInner">{child}</span>}
      </Slot.Slottable>
    </Comp>
  );
}

사용법 (Usage)

import { Button } from "./your-button";

export default () => (
  <Button asChild>
    <a href="/contact">Contact</a>
  </Button>
);

이벤트 핸들러 (Event handlers)

on으로 시작하는 모든 prop(예: onClick)은 이벤트 핸들러로 간주돼요.

이벤트 핸들러를 병합할 때 Slot은 자식 핸들러가 슬롯 핸들러보다 우선하는 새 함수를 만들게 돼요.

이벤트 핸들러 중 하나가 event.defaultPrevented에 의존한다면 순서가 올바른지 확인해야 해요.

import { Slot } from "radix-ui";

export default () => (
  <Slot.Root
    onClick={(event) => {
      if (!event.defaultPrevented) console.log("Not logged because default is prevented.");
    }}
  >
    <button onClick={(event) => event.preventDefault()} />
  </Slot.Root>
);

타입이 지정된 슬롯 (Typed slots)

Slot.createSlot은 전달한 이름에 한정된 Slot 컴포넌트를 반환해요. 전달한 이름은 그 오류 메시지에 사용돼요. 이 메서드는 슬롯이 렌더링할 요소와 받을 props를 지정하는 타입 인자를 받아서, 사용하는 쪽이 정확한 타입을 얻도록 해 줘요. Slot.SlotProps도 같은 타입 인자를 받아요.

import * as React from "react";

import { Slot } from "radix-ui";

type ButtonProps = React.ComponentPropsWithoutRef<"button"> & {
  variant?: "solid" | "ghost";
};

const ButtonSlot = Slot.createSlot<HTMLButtonElement, ButtonProps>("Button.Slot");

더 알아보기 (Learn more)