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

react-nestable渲染[object Object]而非预期JSX的问题排查

问题分析

你遇到的核心问题是:react-nestable 默认生成 <ul>/<li> 列表结构,而你返回的 <tr> 是表格行元素,将其嵌套在 <li> 中会导致DOM结构不合法,React元素被强制转换为字符串,最终显示为 [object Object]。此外,部分版本的 react-nestable API参数命名可能与你使用的不一致。


解决方案

方案1:调整react-nestable的标签适配表格结构

react-nestable 支持通过 tag 和 itemTag 属性自定义容器与子项的HTML标签,将其改为表格兼容的标签即可:

<table style={{ width: "100%", textAlign: "center" }}>
  <Nestable
    items={items}
    renderItem={renderItems} // 注意:部分版本的组件使用单数`renderItem`而非`renderItems`
    tag="tbody"
    itemTag="tr"
  />
</table>

同时需要确认渲染函数的参数格式,部分版本的组件直接传递item对象而非包裹在对象中,调整如下:

const renderItems = (item) => {
  switch (item.type) {
    // 保留原有的JSX渲染逻辑
    case "button1":
      return (
        <tr style={{ backgroundColor: "#ffffff" }}>
          <td colSpan="2" style={{ padding: "16px" }}>
            <button
              contentEditable="true"
              style={{
                border: "none",
                outline: "none",
                backgroundColor: "#2563eb",
                borderRadius: "7px",
                padding: "8px 12px",
                color: "#ffffff",
                fontWeight: "500",
                letterSpacing: "0.5px"
              }}
            >
              {item.text}
            </button>
          </td>
        </tr>
      )
    case "button2":
      return (
        <tr style={{ backgroundColor: "#ffffff" }}>
          <td style={{ padding: "16px" }}>
            <button
              contentEditable="true"
              style={{
                border: "none",
                outline: "none",
                backgroundColor: "#db2777",
                borderRadius: "7px",
                padding: "8px 12px",
                color: "#ffffff",
                fontWeight: "500",
                letterSpacing: "0.5px"
              }}
            >
              {item.text[0]}
            </button>
          </td>
          <td style={{ padding: "16px" }}>
            <button
              contentEditable="true"
              style={{
                border: "none",
                outline: "none",
                backgroundColor: "#2563eb",
                borderRadius: "7px",
                padding: "8px 12px",
                color: "#ffffff",
                fontWeight: "500",
                letterSpacing: "0.5px"
              }}
            >
              {item.text[1]}
            </button>
          </td>
        </tr>
      )
  }
}

方案2:替换为表格友好的拖拽排序组件

如果react-nestable的结构无法完全适配表格需求,推荐使用专门支持表格的拖拽组件,以下是react-sortable-hoc的集成示例:

import { SortableContainer, SortableElement } from 'react-sortable-hoc';
import arrayMove from 'array-move';

// 定义可排序的表格行组件
const SortableItem = SortableElement(({ item }) => {
  switch (item.type) {
    case "button1":
      return (
        <tr style={{ backgroundColor: "#ffffff" }}>
          <td colSpan="2" style={{ padding: "16px" }}>
            <button
              contentEditable="true"
              style={{
                border: "none",
                outline: "none",
                backgroundColor: "#2563eb",
                borderRadius: "7px",
                padding: "8px 12px",
                color: "#ffffff",
                fontWeight: "500",
                letterSpacing: "0.5px"
              }}
            >
              {item.text}
            </button>
          </td>
        </tr>
      )
    case "button2":
      return (
        <tr style={{ backgroundColor: "#ffffff" }}>
          <td style={{ padding: "16px" }}>
            <button
              contentEditable="true"
              style={{
                border: "none",
                outline: "none",
                backgroundColor: "#db2777",
                borderRadius: "7px",
                padding: "8px 12px",
                color: "#ffffff",
                fontWeight: "500",
                letterSpacing: "0.5px"
              }}
            >
              {item.text[0]}
            </button>
          </td>
          <td style={{ padding: "16px" }}>
            <button
              contentEditable="true"
              style={{
                border: "none",
                outline: "none",
                backgroundColor: "#2563eb",
                borderRadius: "7px",
                padding: "8px 12px",
                color: "#ffffff",
                fontWeight: "500",
                letterSpacing: "0.5px"
              }}
            >
              {item.text[1]}
            </button>
          </td>
        </tr>
      )
  }
});

// 定义可排序的表格容器
const SortableTable = SortableContainer(({ items }) => {
  return (
    <table style={{ width: "100%", textAlign: "center" }}>
      <tbody>
        {items.map((item, index) => (
          <SortableItem key={item.id} index={index} item={item} />
        ))}
      </tbody>
    </table>
  );
});

// 组件内使用
const MyComponent = () => {
  const [items, setItems] = useState(template);

  const onSortEnd = ({ oldIndex, newIndex }) => {
    setItems(arrayMove(items, oldIndex, newIndex));
  };

  return <SortableTable items={items} onSortEnd={onSortEnd} />;
};

验证要点
  1. 确认react-nestable版本:旧版本API可能使用renderItem(单数)而非renderItems(复数)
  2. 检查DOM结构:确保<tr>仅嵌套在<table>的<tbody>/<thead>/<tfoot>容器内,避免出现在列表元素中

内容的提问来源于stack exchange,提问作者Siddhartha Sahu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:27:50