При организации компонентов в React используется подход, когда компонент разбивается на несколько частей и доступ к каждой части происходит через точку, например Card и Card.Header, Card.Body и Card.Footer.
Есть несколько способов реализовать такой подход, например через Function Assignment:
function Card() {}
Card.Header = function Header() {}
Card.Body = function Body() {}
Card.Footer = function Footer() {}
export default Card;
Либо через Object.assign:
export default Object.assign(Card, {
Header,
Body,
Footer,
});
У обоих этих подходов есть минусы:
🔴 Проблема с сериализацией, из-за чего этот подход не будет работать в React Server Components.
🔴 Проблема с tree shaking: все части компонента будут затянуты в бандл, даже если будет использоваться только одна из них.
Для решения этих проблем можно использовать современный способ через ES модули. Пример:
// card.tsx
export function CardRoot() {}
export function CardHeader() {}
export function CardBody() {}
export function CardFooter() {}
// namespaces.ts
export {
CardBody as Body,
CardRoot as Root,
CardFooter as Footer,
CardHeader as Header,
} from "./card";
// index.tsx
export * as Card from "./namespace";
// App.tsx
import { Card } from './src/ui/card';
// Card.Root, Card.Body и т.д.
В этом способе нет runtime вычислений и код работает в React Server Components.
Дополнено: однако из-за особенностей работы бандлера, tree shaking все равно работать не будет.
https://ivicabatinic.from.hr/posts/multipart-namespace-components-addressing-rsc-and-dot-notation-issues