You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React如何根据传入图标条件动态修改Alert组件样式

问题根因

原判断逻辑失效的核心原因:每次书写JSX标签<XxxIcon />时,React都会生成全新的元素对象,即便引用的是同一个图标组件,不同位置/不同次渲染生成的对象内存引用完全不同,直接用===做全等对比永远返回false,永远无法进入你写的判断分支。

推荐实现方案

不要直接把JSX元素作为判断依据,改用类型字符串做标识,统一维护图标、样式的映射关系,可维护性更高:

  1. 重写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;
  1. 调整调用方,传入类型标识而非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;
  1. 在样式文件中定义不同类型的配色
.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:18:05