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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:25:22