ReactTS中如何实现类switch语句的条件渲染Switch HOC?
React TypeScript 实现类switch语义的条件渲染组件
注意:这种嵌套子组件的调用语法属于复合组件模式,相比纯HOC更贴合你给出的使用示例,不需要额外包装现有业务组件。核心实现逻辑完全对齐原生switch语句的短路匹配规则,不存在额外DOM包裹,渲染行为完全匹配你给出的规则要求。
组件分层实现
整套实现由三个无冗余逻辑的组合组件构成,Switch负责联动识别内部的Case、Default子组件,执行匹配逻辑。
1. 类型定义(TS 强类型约束)
import React, { ReactNode } from 'react'; interface CaseProps { /** Case 命中判断条件 */ condition: boolean; children: ReactNode; } interface DefaultProps { /** 所有Case未命中时的兜底内容 */ children: ReactNode; } interface SwitchProps { children: ReactNode; }
2. 子组件占位实现
Case 和 Default 本身不需要承载渲染逻辑,仅作为类型标记存在,方便Switch组件识别对应节点:
// Case 透传组件,仅做类型标记 const Case: React.FC<CaseProps> = ({ children }) => { return <>{children}</>; }; // Default 透传组件,仅做兜底标记 const Default: React.FC<DefaultProps> = ({ children }) => { return <>{children}</>; };
3. 核心Switch逻辑
Switch组件负责按书写顺序遍历子节点,执行短路匹配:找到第一个condition为真的Case即停止遍历,直接返回该Case的内容;若遍历完所有Case都未命中,则返回之前识别到的Default内容。
const Switch: React.FC<SwitchProps> = ({ children }) => { // 兼容嵌套child的异常情况,将子元素转成可遍历数组 const childNodes = React.Children.toArray(children); let matchedCaseContent: ReactNode = null; let defaultFallbackContent: ReactNode = null; for (const node of childNodes) { // 识别Case节点,命中第一个符合条件的即终止遍历 if (React.isValidElement<CaseProps>(node) && node.type === Case) { if (node.props.condition) { matchedCaseContent = node.props.children; break; } } // 识别Default节点,缓存为兜底内容 if (React.isValidElement<DefaultProps>(node) && node.type === Default) { defaultFallbackContent = node.props.children; } } // 优先返回匹配到的Case内容,无匹配则返回Default内容 return <>{matchedCaseContent ?? defaultFallbackContent}</>; };
实际使用效果
完全匹配你给出的调用语法,渲染规则和原生switch一致:
// 调用示例 const PageDemo = ({ cond1, cond2 }: { cond1: boolean; cond2: boolean }) => { return ( <Switch> <Case condition={cond1}> Hello </Case> <Case condition={cond2}> World </Case> <Default> Hi stranger </Default> </Switch> ); };
对应渲染行为:
cond1为true时,直接渲染「Hello」,忽略后续所有Casecond1为false、cond2为true时,渲染「World」- 两个条件均为false时,渲染「Hi stranger」
优化点:统一导出三个组件,避免外部传入非预期的子元素破坏组件逻辑:
export { Switch, Case, Default };
内容的提问来源于stack exchange,提问作者Nikhil Goyal
相关产品推荐
相关产品推荐

