Chakra UI多部分组件子组件__css样式不生效问题
Chakra UI 自定义多部分组件子项样式不生效问题
问题现象
基于 create-react-app 搭建的 TypeScript + React 项目中使用 Chakra UI 开发时,自定义 <Dropdown> 根组件的 CSS 样式可正常应用,但内部 <DropdownItem> 组件配置的样式完全不生效:
- 代码参考 Chakra UI 官方多部分组件样式配置文档编写,和官方源码中 List 组件的实现逻辑对比无明显异常
- 项目运行无控制台报错
- 打印
useStyles()、useMultiStyleConfig()返回的 CSSDict 样式对象内容正常,初步定位问题出在__css={styles.item}的属性传递环节
相关代码
Select.tsx(组件调用处)
<Dropdown onClick={() => setOpen(!open)}> <DropdownItem>{currItem}</DropdownItem> </Dropdown>
Dropdown.tsx(自定义组件实现)
const [StylesProvider, useStyles] = createStylesContext("Dropdown"); export function Dropdown(props: any): any { const { size, variant, children, ...rest } = props; const styles = useMultiStyleConfig("Dropdown", { size, variant }); return ( <List __css={styles.dropdown} {...rest}> <StylesProvider value={styles}>{children}</StylesProvider> </List> ); } export function DropdownItem(props: any): any { const styles = useStyles(); return <ListItem __css={styles.item} {...props} />; }
theme.ts(全局主题配置)
export const theme = extendTheme({ components: { Button, Dropdown, }, colors: { main: { independence: "#3D405B", purplenavy: "#51557A", darkbluegray: "#656A99", terracotta: "#E07A5F", eggshell: "#F4F1DE", }, }, styles: { global: () => ({ body: { bg: "main.independence", height: "100%", }, }), }, shadows: { terra: "2px -2px #E07A5F", eggshell: "2px -2px #F4F1DE", }, });
dropdown.style.ts(Dropdown 组件主题配置)
export const Dropdown: ComponentStyleConfig = { parts: ["dropdown", "item"], // 各部件基础样式 baseStyle: { dropdown: { position: "relative", display: "inline-block", width: "100px", cursor: "pointer", fontSize: "calc(35px, 0.87vw)", h: "100%", zIndex: "10", }, item: { h: "100%", display: "flex", justifyContent: "center", alignItems: "center", _hover: { bg: "main.violetLt", borderRadius: "15px 0 0 15px" }, fontWeight: "600", bg: "orange", }, }, // 尺寸样式 sizes: {}, // 变体样式 variants: {}, // 默认参数 defaultProps: {}, };
排查过程
- 通过 React Devtools 查看组件树,
<List>对应内部 ListElement 是最后一个能接收到正确__css属性的组件,它渲染出的<li>真实子节点上__css属性直接消失。 - 将 DropdownItem 内的
<ListItem>替换为<chakra.li>后,__css属性可正常传递,样式成功应用,但未第一时间定位到该现象的根本原因。
根本原因
问题来自 Chakra UI 内置多部分组件的样式上下文隔离逻辑:
<ListItem>是官方 List 多部分组件的内置子部件,内部默认绑定 List 组件的独立样式上下文,会优先读取 List 自身 StylesProvider 下的item样式,外部传入的__css属性会被内部逻辑覆盖。- 自定义 Dropdown 组件通过
createStylesContext创建了全新的独立样式上下文,<ListItem>不会读取这个上下文里的styles.item配置,最终传入的__css在 ListItem 内部被丢弃,没有传递到最终渲染的 DOM 节点。 <chakra.li>是最基础的 Chakra DOM 包装标签,没有内置多部分组件的上下文读取逻辑,会直接透传并应用传入的__css属性,因此替换后样式可正常生效。
修复方案
两种方案均可解决问题,按需选择即可:
- 方案一:直接将
<ListItem>替换为<chakra.li>,脱离 List 组件的内置样式逻辑,现有__css={styles.item}写法无需修改即可正常生效,是侵入性最低的方案。 - 方案二:如果需要保留
<ListItem>的其他内置特性,将__css属性替换为优先级更高的sx属性传入,即写成<ListItem sx={styles.item} {...props} />,sx 属性不会被组件内置样式覆盖。
内容的提问来源于stack exchange,提问作者isdn
相关产品推荐
相关产品推荐

