如何为数组内的ReactJS组件统一添加className?
问题:如何统一为React图标组件添加className,无需逐个手动编写?
我有一个包含图标组件和标题的对象数组:
const skills = [ { icon: <FaHtml5 className="skill-icon" />, title: "HTML5" }, { icon: <FaCss3 className="skill-icon" />, title: "CSS3" }, { icon: <SiJavascript className="skill-icon" />, title: "JavaScript" }, { icon: <FaReact className="skill-icon" />, title: "ReactJS" }, { icon: <SiBootstrap className="skill-icon" />, title: "Bootstrap" }, ];
目前我需要为每个组件手动编写className="skill-icon",尝试了以下方式添加className但无效:
skills.map((add_class) => { add_class.icon.add.classList("myClass"); console.log(add_class); });
是否必须像这样在数组内逐个添加className,还是有其他方式遍历所有组件统一添加?
我的渲染结构如下:
<section className="skill-card-section"> {skills.map((skill) => { return ( <section className="skill-card" key={skill.title}> {skill.icon} <p className="skill-title">{skill.title}</p> </section> ); })} </section>
解决方案
为什么你的尝试无效
skill.icon是React虚拟DOM元素对象,不是浏览器真实DOM节点,add.classList是真实DOM节点的专属方法,直接调用会报错,无法生效。
方法1:重构数组,渲染时统一添加className(推荐)
把数组里的图标改为存储组件类/函数,而非已创建的React元素,这样渲染时可以统一传入props:
// 重构skills数组 const skills = [ { Icon: FaHtml5, title: "HTML5" }, { Icon: FaCss3, title: "CSS3" }, { Icon: SiJavascript, title: "JavaScript" }, { Icon: FaReact, title: "ReactJS" }, { Icon: SiBootstrap, title: "Bootstrap" }, ];
渲染时动态创建组件并传入className:
<section className="skill-card-section"> {skills.map((skill) => { return ( <section className="skill-card" key={skill.title}> {/* 统一添加className */} <skill.Icon className="skill-icon" /> <p className="skill-title">{skill.title}</p> </section> ); })} </section>
方法2:使用React.cloneElement克隆元素并添加className
如果不想修改原数组,可在渲染时通过React.cloneElement克隆原图标元素,添加或合并className:
import React from 'react'; <section className="skill-card-section"> {skills.map((skill) => { // 克隆图标元素,自动合并原有的className(如果存在) const styledIcon = React.cloneElement(skill.icon, { className: `skill-icon ${skill.icon.props.className || ''}` }); return ( <section className="skill-card" key={skill.title}> {styledIcon} <p className="skill-title">{skill.title}</p> </section> ); })} </section>
如果需要更健壮的className合并(比如处理多类名场景),可以使用classnames库简化逻辑:
import classNames from 'classnames'; const styledIcon = React.cloneElement(skill.icon, { className: classNames('skill-icon', skill.icon.props.className) });
方法3:批量更新原数组中的图标元素(不推荐)
因为React元素是不可变对象,无法直接修改,需要重新创建元素并生成新数组:
import React from 'react'; const updatedSkills = skills.map(skill => ({ ...skill, icon: React.cloneElement(skill.icon, { className: "skill-icon" }) }));
之后使用updatedSkills进行渲染即可。
内容的提问来源于stack exchange,提问作者Saran Pariyar
相关产品推荐
相关产品推荐

