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
相关产品推荐
相关产品推荐

