React中如何修改迭代渲染的实例化组件属性?
问题场景
现有代码逻辑是遍历配置数组渲染按钮,数组中存储了已经实例化的react-icons图标组件,需要动态覆盖图标的size属性,现有代码如下:
// 按钮组件 export const AdmButton = ({icon,title,iconSize}) =>{ return({icon} {title}) }
// 遍历渲染逻辑 buttondata.map((el, index) => { <AdmButton title={el.title} icon={el.icon} iconSize="3em"/> })
// 按钮配置数据 export const buttondata=[{ title:'calc', icon: <ImIcons.ImCalculator size="2em"/>, },/*...*/ ]
核心问题:配置项里存的是已经创建完成的React元素实例,直接传入组件后无法直接修改实例内置的size属性。
实现方案
方案1(推荐):存储组件引用而非实例,使用时动态传参
这是最符合React设计逻辑的方案,没有额外API开销,后续扩展属性也更方便。
- 修改配置数组,不要直接写JSX实例化图标,改为存储图标组件本身的引用:
export const buttondata=[ { title:'calc', // 注意不要加<>/,直接存组件引用,命名改为大写开头符合组件规范 Icon: ImIcons.ImCalculator, }, /*...其余配置项保持结构一致即可*/ ]
- 修改AdmButton组件,接收组件引用后在内部实例化,直接传入需要的
size属性:
export const AdmButton = ({Icon, title, iconSize}) =>{ return ( // 多元素返回用Fragment或者实际的button标签包裹 <> <Icon size={iconSize} /> {title} </> ) }
- 遍历渲染时传入组件引用即可,注意补全map要求的
key属性,以及补全return避免返回undefined:
buttondata.map((el) => { // key优先用业务唯一id,没有的话临时用title或者index return <AdmButton key={el.title} title={el.title} Icon={el.Icon} iconSize="3em"/> })
方案2:用React.cloneElement克隆已有元素覆盖属性
如果配置数组结构无法修改(比如数据由第三方模块返回,已经是固定的实例化元素),可以用React内置的cloneElement方法克隆传入的图标元素,合并覆盖props:
只需要修改AdmButton组件即可,其余代码不用动:
// 先引入cloneElement方法 import { cloneElement } from 'react'; export const AdmButton = ({icon, title, iconSize}) =>{ return ( <> {/* 克隆传入的icon实例,新传入的size会覆盖原有实例上的size属性,其余props保留 */} {cloneElement(icon, { size: iconSize })} {title} </> ) }
注意:这个方案需要兜底判断传入的icon是否为合法React元素,否则cloneElement会抛出报错。
原有代码的其他问题修正
- 遍历渲染列表时必须给列表根节点加唯一
key属性,否则React会抛出渲染警告,列表动态重排时也会出现状态错乱问题 - 箭头函数返回JSX时,如果函数体写了大括号
{},必须手动写return返回内容,否则map遍历会返回undefined,无法渲染出组件;如果要隐式返回,需要把大括号换成小括号() - JSX中返回多个平级元素时,必须用父标签或者Fragment
<></>包裹,不能直接写({icon} {title})这种语法。
内容的提问来源于stack exchange,提问作者Germán
相关产品推荐
相关产品推荐

