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

ReactJS组件中如何单独控制Textarea的行数展开与收起

解决React循环渲染中单个textarea展开/收缩的问题

你遇到的问题根源在于所有循环生成的textarea共享了同一个inputRows状态——当你点击任意一个textarea时,修改的是全局的状态值,导致所有组件都跟着更新行数。

要实现仅触发被点击的textarea变化,需要把状态改成针对每个独立项的记录,具体步骤如下:

1. 调整状态结构

把原来单一数值的inputRows改成对象,用每个子项的key作为属性名,存储对应textarea的行数:

// 初始化时,给每个criteria子项设置初始行数1
const [inputRows, setInputRows] = React.useState(
  criteria.children.reduce((acc, c) => ({ ...acc, [c.key]: 1 }), {})
);

如果criteria.children是动态加载的,也可以初始化为空对象,后续点击时再动态添加属性,此时textarea的rows属性用inputRows[c.key] || 1兜底。

2. 修改事件处理逻辑

点击和失焦事件只更新当前子项对应的状态值,使用函数式更新确保状态的正确覆盖:

onClick={() => setInputRows(prev => ({ ...prev, [c.key]: 10 }))}
onBlur={() => setInputRows(prev => ({ ...prev, [c.key]: 1 }))}

3. 绑定对应状态到textarea

让每个textarea的rows属性读取自身key对应的状态值:

rows={inputRows[c.key]}

修改后的完整代码片段

// 初始化每个子项的行数状态
const [inputRows, setInputRows] = React.useState(
  criteria.children.reduce((acc, c) => ({ ...acc, [c.key]: 1 }), {})
); 

criteria.children.map((c) => {
  return (
    <tr key={c.key} className="ant-table-row ant-table-row-level-0">
      <td className="ant-table-cell" style={{ textAlign: "center" }}>
        <Form.Item
          key={c.key + "_rating"}
          style={{ marginBottom: "0px" }}
          name={c.key + "_rating"}
        >
          <InputNumber
            className={
              "text-center" +
              (!isIndexed(c.key) ? " rating_not_indexed" : "")
            }
            formatter={(value) =>
              `${
                value.toString().length == 0
                  ? ""
                  : isNaN(Math.round(value * 100) / 100)
                  ? ""
                  : Math.round(value * 100) / 100
              }`
            }
            min={0}
            max={3}
            step={1}
          />
        </Form.Item>
      </td>
      <td className="ant-table-cell">
        <Tooltip
          placement="right"
          title={form.getFieldValue(c.key + "_comment")}
        >
          <Form.Item
            style={{ marginBottom: "0px" }}
            name={c.key + "_comment"}
          >
            <textarea
              rows={inputRows[c.key]}
              className="textarea"
              onClick={() => setInputRows(prev => ({ ...prev, [c.key]: 10 }))}
              onBlur={() => setInputRows(prev => ({ ...prev, [c.key]: 1 }))}
              tabIndex={-1}
            ></textarea>
          </Form.Item>
        </Tooltip>
      </td>
    </tr>
  );
})

这样修改后,每个textarea的状态都是独立维护的,点击其中一个只会更新自身的行数,不会影响其他textarea。

内容的提问来源于stack exchange,提问作者Ezz Redfox

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:45:58