React中点击卡片按钮设置contentEditable报错的排查与解决
问题原因分析
你遇到的错误根源是:item.Content是字符串类型(从JSON数据读取的原始文本),你试图给字符串添加contentEditable属性——JavaScript中字符串属于原始值,无法动态添加属性,因此抛出类型错误。
另外,直接修改item对象的方式也不符合React状态管理逻辑,React组件的UI应该由状态驱动,而非直接修改数据对象。
解决方案
要实现点击编辑按钮让卡片内容可编辑,需通过React状态控制每个卡片的编辑状态,具体步骤如下:
1. 添加编辑状态跟踪
在Products组件内新增状态,记录哪些卡片处于编辑状态(用卡片的唯一标识,比如item.Id,假设你的articles数据包含该字段):
const [editingIds, setEditingIds] = React.useState(new Set());
2. 编写状态切换函数
将编辑逻辑移到Products组件内部,实现编辑状态的切换:
const toggleEdit = (itemId) => { setEditingIds(prev => { const newSet = new Set(prev); newSet.has(itemId) ? newSet.delete(itemId) : newSet.add(itemId); return newSet; }); };
3. 传递状态与函数到子组件
修改ListView的item属性,把状态和切换函数传递给MyItemRender:
<ListView data={filteredList.slice(skip, skip + take)} item={(props) => <MyItemRender {...props} editingIds={editingIds} toggleEdit={toggleEdit} />} style={{ width: '100%', height: '100%', }} />
4. 渲染可编辑内容
修改MyItemRender组件,根据编辑状态给内容元素设置contentEditable属性,同时替换硬编码文本为item.Content:
const MyItemRender = (props) => { const { dataItem, editingIds, toggleEdit } = props; const isEditing = editingIds.has(dataItem.Id); return ( <div style={{ padding: '20px 20px' }} className="parent-container" > <div className="k-card-list"> <Card style={{ width: 260, height: 340 }}> <CardBody style={{ borderBottom: 'solid 1px rgba(0,0,0,.08)' }}> <CardImage src={require(`../assets/article-images/${dataItem.Image}`)} style={{ width: 260, height: 140, maxWidth: 260 }} /> <CardTitle style={{ fontSize: 18 }} /> <CardTitle>{dataItem.Title}</CardTitle> <CardTitle>{dataItem.Subtitle}</CardTitle> {/* 可编辑内容区域 */} <p className="content" contentEditable={isEditing} suppressContentEditableWarning={true} > {dataItem.Content} </p> </CardBody> <CardActions> <div className="footer-buttons-container"> <span> <span className="k-button k-button-md k-button-rectangle k-rounded-md k-button-flat k-button-flat-base"> <span className="k-icon k-i-preview"></span>Review </span> </span> <span> <span className="k-button k-edit-button k-button-md k-button-rectangle k-rounded-md k-button-flat k-button-flat-primary" onClick={() => toggleEdit(dataItem.Id)} > <span className="k-icon k-i-edit"></span>{isEditing ? '保存' : 'Edit'} </span> </span> </div> </CardActions> </Card> </div> </div> ); };
可选:添加内容保存逻辑
如果需要保存编辑后的内容,可监听onBlur事件同步回状态:
// 在Products组件内添加 const handleContentSave = (e, item) => { setFilteredList(prev => prev.map(post => { if (post.Id === item.Id) { return {...post, Content: e.currentTarget.textContent}; } return post; })); }; // 在MyItemRender的p标签上添加 <p className="content" contentEditable={isEditing} suppressContentEditableWarning={true} onBlur={(e) => handleContentSave(e, dataItem)} > {dataItem.Content} </p>
内容的提问来源于stack exchange,提问作者Robert Jefferson
相关产品推荐
相关产品推荐

