apps/docs/content/docs/cn/react/releases/v3-0-0-alpha-35.mdx
此版本修复了一个关键问题:复合组件在 React Server Components(RSC)中无法正常工作。同时,本版本采用了 React 19 的最佳实践,移除了 forwardRef,并简化了 Context 的使用方式。Switch 组件已经过重构,与 Radio / RadioGroup 模式保持一致,提供更清晰、更统一的 API。
升级到最新版本:
<Tabs items={["npm", "pnpm", "yarn", "bun"]}>
<Tab value="npm">
bash npm i @heroui/styles@alpha @heroui/react@alpha
</Tab>
<Tab value="pnpm">
bash pnpm add @heroui/styles@alpha @heroui/react@alpha
</Tab>
<Tab value="yarn">
bash yarn add @heroui/styles@alpha @heroui/react@alpha
</Tab>
<Tab value="bun">
bash bun add @heroui/styles@alpha @heroui/react@alpha
</Tab>
</Tabs>
复合组件现在可以在 React Server Components 中正常工作。此前的实现把复合模式逻辑放在了组件内部,与 "use client" 指令存在冲突。通过将模式逻辑迁移到组件的索引文件中,这一问题已被修复。
本版本采用了 React 19 的最佳实践:
forwardRef:在 React 19 中已不再需要,ref 现在可以作为普通的 prop 使用(参见 React 19 文档)Context.Provider 替换为直接使用 Context(参见 React 19 文档)Switch 组件已经过重构,遵循与 Radio / RadioGroup 相同的清晰拆分模式:
<SwitchGroup> 取代了嵌套的 <Switch.Group> 与 <Switch.GroupItems> 模式之前:
<Switch.Group>
<Switch.GroupItems>
<Switch.Root>...</Switch.Root>
</Switch.GroupItems>
</Switch.Group>
之后:
<SwitchGroup>
<Switch.Root>...</Switch.Root>
<Switch.Root>...</Switch.Root>
</SwitchGroup>
.Root 后缀为支持 React Server Components,复合组件模式已经过重构。在使用复合写法时,主组件现在需要带上 .Root 后缀。
之前:
import { Avatar } from "@heroui/react"
<Avatar>
<Avatar.Image src="/images/avatar.jpeg" alt="Junior Garcia" />
<Avatar.Fallback>JR</Avatar.Fallback>
</Avatar>
之后:
import { Avatar } from "@heroui/react"
<Avatar.Root>
<Avatar.Image src="/images/avatar.jpeg" alt="Junior Garcia" />
<Avatar.Fallback>JR</Avatar.Fallback>
</Avatar.Root>
说明: 命名导出(例如 <Avatar>、<AvatarImage>、<AvatarFallback>)保持不变,依然完全支持。
Switch 组件的分组 API 已经过重构,与 Radio / RadioGroup 模式保持一致:
之前:
import { Switch } from "@heroui/react"
<Switch.Group orientation="horizontal">
<Switch.GroupItems>
<Switch.Root name="notifications">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Notifications</Label>
</Switch.Root>
<Switch.Root name="marketing">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Marketing</Label>
</Switch.Root>
</Switch.GroupItems>
</Switch.Group>
之后:
import { Switch, SwitchGroup } from "@heroui/react"
<SwitchGroup orientation="horizontal">
<Switch.Root name="notifications">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Notifications</Label>
</Switch.Root>
<Switch.Root name="marketing">
<Switch.Control>
<Switch.Thumb />
</Switch.Control>
<Label>Marketing</Label>
</Switch.Root>
</SwitchGroup>
这次变更带来了:
<SwitchGroup> 取代了嵌套的 <Switch.Group> 与 <Switch.GroupItems> 模式迁移步骤:
SwitchGroup:import { Switch, SwitchGroup } from "@heroui/react"<Switch.Group> 替换为 <SwitchGroup><Switch.GroupItems> 包装Switch.Root 组件��持不变所有复合组件都受到影响:
Accordion → Accordion.RootAvatar → Avatar.RootCard → Card.RootDisclosure → Disclosure.RootFieldset → Fieldset.RootKbd → Kbd.RootLink → Link.RootPopover → Popover.RootRadioGroup → RadioGroup.RootSwitch → Switch.RootTabs → Tabs.RootTooltip → Tooltip.Root使用 HeroUI 的复合组件有两种选择:
.Root(复合写法)如果你使用的是复合写法(点号语法),请将主组件改为使用 .Root:
Card 示例:
import { Card } from "@heroui/react"
<Card.Root>
<Card.Header>
<Card.Title>Card Title</Card.Title>
<Card.Description>Card description</Card.Description>
</Card.Header>
<Card.Content>
Card content
</Card.Content>
<Card.Footer>
Card footer
</Card.Footer>
</Card.Root>
Tabs 示例:
import { Tabs } from "@heroui/react"
<Tabs.Root>
<Tabs.ListWrapper>
<Tabs.List>
<Tabs.Tab id="tab1">Tab 1<Tabs.Indicator /></Tabs.Tab>
<Tabs.Tab id="tab2">Tab 2<Tabs.Indicator /></Tabs.Tab>
</Tabs.List>
</Tabs.ListWrapper>
<Tabs.Panel id="tab1">Panel 1</Tabs.Panel>
<Tabs.Panel id="tab2">Panel 2</Tabs.Panel>
</Tabs.Root>
Avatar 示例:
import { Avatar } from "@heroui/react"
<Avatar.Root>
<Avatar.Image alt="John Doe" src="..." />
<Avatar.Fallback>JD</Avatar.Fallback>
</Avatar.Root>
我们已经为所有复合组件添加了命名导出支持,你可以这样使用:
Card 示例:
import {
CardRoot,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@heroui/react"
<CardRoot>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card description</CardDescription>
</CardHeader>
<CardContent>
Card content
</CardContent>
<CardFooter>
Card footer
</CardFooter>
</CardRoot>
Tabs 示例:
import { TabsRoot, TabListContainer, TabList, Tab, TabIndicator, TabPanel } from "@heroui/react"
<TabsRoot>
<TabListContainer>
<TabList>
<Tab id="tab1">Tab 1<TabIndicator /></Tab>
<Tab id="tab2">Tab 2<TabIndicator /></Tab>
</TabList>
</TabListContainer>
<TabPanel id="tab1">Panel 1</TabPanel>
<TabPanel id="tab2">Panel 2</TabPanel>
</TabsRoot>
Avatar 示例:
import { Avatar, AvatarImage, AvatarFallback } from "@heroui/react"
<Avatar>
<AvatarImage alt="John Doe" src="..." />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
如果你使用的是复合写法,只需将主组件改为使用 .Root:
查找复合组件的所有使用位置(例如内部包含 <Avatar.Image> 等的 <Avatar>)
为主组件添加 .Root:
// Before
<Avatar>
<Avatar.Image ... />
</Avatar>
// After
<Avatar.Root>
<Avatar.Image ... />
</Avatar.Root>
就这样! 所有子组件(如 Avatar.Image、Avatar.Fallback)保持不变。
| 组件 | 命名导出写法 | 复合写法(带 .Root) | 额外变更 |
|---|---|---|---|
| Accordion | <Accordion> | <Accordion.Root> | - |
| Avatar | <Avatar> | <Avatar.Root> | - |
| Card | <Card> | <Card.Root> | - |
| Disclosure | <Disclosure> | <Disclosure.Root> | - |
| Fieldset | <Fieldset> | <Fieldset.Root> | - |
| Kbd | <Kbd> | <Kbd.Root> | - |
| Link | <Link> | <Link.Root> | - |
| Popover | <Popover> | <Popover.Root> | - |
| Radio | <Radio> | <Radio.Root> | - |
| Switch | <Switch>、<SwitchControl> | <Switch.Root>、<Switch.Control> | <Switch.Group> → <SwitchGroup>(独立组件) |
| Tabs | <Tabs>、<TabList> | <Tabs.Root>、<Tabs.List> | - |
| Tooltip | <Tooltip>、<TooltipTrigger> | <Tooltip.Root>、<Tooltip.Trigger> | - |
对于使用复合写法的大型代码库,可以借助查找 / 替换:
# Example for Avatar component
# Update the main component to use .Root
sed -i 's/<Avatar>/<Avatar.Root>/g' **/*.tsx
sed -i 's/<\/Avatar>/<\/Avatar.Root>/g' **/*.tsx
# Switch component requires additional steps
# First, ensure SwitchGroup is imported
# Then replace Switch.Group with SwitchGroup
sed -i 's/<Switch\.Group/<SwitchGroup/g' **/*.tsx
sed -i 's/<\/Switch\.Group>/<\/SwitchGroup>/g' **/*.tsx
# Remove Switch.GroupItems wrapper
sed -i 's/<Switch\.GroupItems>//g' **/*.tsx
sed -i 's/<\/Switch\.GroupItems>//g' **/*.tsx
# Repeat for other compound components (Card, Tabs, etc.)
# Note: This only affects files using the compound pattern
重要事项:
SwitchGroup 已被导入:import { Switch, SwitchGroup } from "@heroui/react"这次变更是修复 React Server Components 兼容性所必需的。此前的实现存在一些架构上的限制:
"use client" 指令存在冲突forwardRef 与 Context.Provider 等已被弃用的写法组件文档将同步更新,以反映新的写法:
.Root 的复合写法如果你在迁移过程中遇到任何问题:
.Root(例如 <Avatar> → <Avatar.Root>)感谢每一位为本次发布做出贡献的开发者,是你们让 React Server Components 支持与 React 19 兼容性得到了改进!