React如何根据传入图标条件动态修改Alert组件样式
问题根因
原判断逻辑失效的核心原因:每次书写JSX标签<XxxIcon />时,React都会生成全新的元素对象,即便引用的是同一个图标组件,不同位置/不同次渲染生成的对象内存引用完全不同,直接用===做全等对比永远返回false,永远无法进入你写的判断分支。
推荐实现方案
不要直接把JSX元素作为判断依据,改用类型字符串做标识,统一维护图标、样式的映射关系,可维护性更高:
- 重写Alert组件,内置类型映射表
import "./index.scss"; import { BsInfoCircleFill, BsCheckCircleFill } from "react-icons/bs"; import { MdOutlineWarning } from "react-icons/md"; // 类型-图标-样式类映射表 const ALERT_CONFIG = { info: { icon: <BsInfoCircleFill />, themeClass: "alert--info" }, success: { icon: <BsCheckCircleFill />, themeClass: "alert--success" }, warning: { icon: <MdOutlineWarning />, themeClass: "alert--warning" } } function Alert(props) { // 默认兜底info类型 const { type = "info", message } = props; const config = ALERT_CONFIG[type]; return ( <div className={`alert-box ${config.themeClass}`}> <div className="alert-content"> <span className="alert-icon">{config.icon}</span> <p className="alert-msg">{message}</p> </div> </div> ); } export default Alert;
- 调整调用方,传入类型标识而非JSX图标
import Alert from "./Alert"; import "./index.scss"; function App() { return ( <div className="App"> <div className="main"> <Alert type="info" message="blah blah blah" /> <Alert type="success" message="blah blah blah" /> <Alert type="warning" message="blah blah blah" /> <Alert type="warning" message="blah blah blah" /> </div> </div> ); } export default App;
- 在样式文件中定义不同类型的配色
.alert-box { padding: 12px 16px; border-radius: 6px; display: flex; align-items: center; gap: 8px; // 信息类型样式 &.alert--info { background-color: #e6f4ff; border: 1px solid #91caff; color: #1677ff; } // 成功类型样式 &.alert--success { background-color: #f6ffed; border: 1px solid #b7eb8f; color: #52c41a; } // 警告类型样式 &.alert--warning { background-color: #fffbe6; border: 1px solid #ffe58f; color: #faad14; } }
备选方案(保留原传icon写法)
如果不想改动现有调用方式,必须直接传JSX图标,可以通过React元素的type属性拿到原始组件引用做判断,这种方式可以绕过对象引用不一致的问题:
function Alert(props) { const { icon, message } = props; let themeClass = "alert--info"; // 注意这里对比的是icon.type,也就是原始组件函数/类的引用 if (icon.type === BsCheckCircleFill) { themeClass = "alert--success" } if (icon.type === MdOutlineWarning) { themeClass = "alert--warning" } return ( <div className={`alert-box ${themeClass}`}> <div className="alert-content"> <span className="alert-icon">{icon}</span> <p className="alert-msg">{message}</p> </div> </div> ); }
注意:这种方案兼容性较差,如果后续给图标外层套了其他组件(比如加了Tooltip包裹),
icon.type就会变成外层包裹组件,判断逻辑会直接失效,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者AntoMac
相关产品推荐
相关产品推荐

