如何优化React中基于Props切换Material UI组件样式的冗余代码?
需求
我想要修改Material UI中的部分组件颜色,同时创建一个可通过Props切换颜色的React组件。
问题
我使用withStyles创建了多个不同颜色的组件,将它们封装在另一个组件中,通过传入指定颜色名称的props来切换对应组件。
当前代码存在大量无意义的重复内容。
原始代码
import React from 'react' import Rating from "@material-ui/lab/Rating"; import { withStyles } from '@material-ui/core'; const StyledRating_Red = withStyles({ iconFilled: { color: "red" } })(Rating); const StyledRating_Green = withStyles({ iconFilled: { color: "green" } })(Rating); const StyledRating_Blue = withStyles({ iconFilled: { color: "blue" } })(Rating); type FormRowProps = { scale: number; colorstyle: "red" | "green" | "blue"; }; const FormRow: React.FC<FormRowProps> = ({ scale, colorstyle }) => { return ( <React.StrictMode> {("red" == colorstyle) ? <StyledRating_Red defaultValue={scale} getLabelText={(value: number) => customIcons[value].label}/> : ("green" == colorstyle) ? <StyledRating_Green defaultValue={scale} getLabelText={(value: number) => customIcons[value].label}/> : <StyledRating_Blue defaultValue={scale} getLabelText={(value: number) => customIcons[value].label/> } </React.StrictMode> ); }
注:原始代码末尾的StyledRating_Blue组件存在标签未正确闭合的语法问题,优化后的代码已修复该问题。
优化方案
你当前的代码冗余点在于重复声明了多个结构完全一致的样式组件,且用嵌套三元判断维护渲染分支,后续新增颜色需要同时修改组件声明、判断逻辑两处代码,维护成本高。可以通过以下两种方案优化:
方案1:withStyles接收props动态生成样式(推荐)
直接利用withStyles支持接收props参数的特性,动态匹配对应颜色,无需提前声明多个组件实例:
import React from 'react' import Rating from "@material-ui/lab/Rating"; import { withStyles, createStyles } from '@material-ui/core'; // 样式函数接收组件props,动态设置填充色 const StyledRating = withStyles((props: { colorstyle: "red" | "green" | "blue" }) => createStyles({ iconFilled: { color: props.colorstyle } }) )(Rating); type FormRowProps = { scale: number; colorstyle: "red" | "green" | "blue"; }; const FormRow: React.FC<FormRowProps> = ({ scale, colorstyle }) => { return ( <React.StrictMode> <StyledRating colorstyle={colorstyle} defaultValue={scale} getLabelText={(value: number) => customIcons[value].label} /> </React.StrictMode> ); }
该方案扩展性最强,后续新增支持的颜色只需要修改colorstyle的联合类型定义即可,无需修改任何业务逻辑。
方案2:颜色配置映射表
如果不同颜色除了填充色还有其他样式差异,可以用配置映射表统一管理所有颜色的样式,后续修改仅需要调整配置:
import React from 'react' import Rating from "@material-ui/lab/Rating"; import { withStyles } from '@material-ui/core'; // 所有颜色样式统一在该映射表维护,新增颜色仅需要加配置项 const COLOR_STYLE_MAP = { red: { iconFilled: { color: "red" } }, green: { iconFilled: { color: "green" } }, blue: { iconFilled: { color: "blue" } }, } as const; // 直接从映射表推导colorstyle的合法值,不用重复写联合类型 type FormRowProps = { scale: number; colorstyle: keyof typeof COLOR_STYLE_MAP; }; const FormRow: React.FC<FormRowProps> = ({ scale, colorstyle }) => { // 动态生成对应样式的Rating组件 const StyledRating = withStyles(COLOR_STYLE_MAP[colorstyle])(Rating); return ( <React.StrictMode> <StyledRating defaultValue={scale} getLabelText={(value: number) => customIcons[value].label} /> </React.StrictMode> ); }
内容的提问来源于stack exchange,提问作者ShortArrow
相关产品推荐
相关产品推荐

