React Textarea光标自动跳至末尾问题排查与修复求助
问题:React Textarea 编辑时光标自动跳转到末尾
在医生开检查单的React应用中,textarea组件存在以下问题:正常输入时光标行为正常,但将光标移至文本中间编辑时,输入一个字符后光标会自动跳转到末尾。如果移除onChange中的逻辑,光标恢复正常,但无法保存textarea的内容。
原组件代码
Textarea组件
React.createElement('textarea', { name: 'SpecialInstruction', id: 'rad_SpecialInstruction', value: this.props.stateobj.SpecialInstruction, onFocus: (event) => { const currentValue = event.target.value; // event.target.value = currentValue + '.'; // this.handleOrderChange(event); // trigger the onChange event handler }, onChange: this.handleOrderChange, className: 'form-control', maxLength: 512, style: { fontSize: '12px !important' }, })
原handleOrderChange方法
_this.handleOrderChange = function (e) { _this.props.AddModuleState(_defineProperty({}, e.target.name, e.target.value), "RAD"); // Store the current cursor position const cursorPosition = e.target.selectionStart; // Prevent the default behavior of the input element e.preventDefault(); _this.props.AddModuleState(_defineProperty({}, e.target.name, e.target.value), "RAD"); // Restore the cursor position e.target.setSelectionRange(cursorPosition, cursorPosition); };
已尝试的修复
移除重复的AddModuleState调用、删除e.preventDefault(),并添加setTimeout恢复光标位置,但问题未完全解决:
_this.handleOrderChange = function (e) { _this.props.AddModuleState(_defineProperty({}, e.target.name, e.target.value), "RAD"); // Store the current cursor position const cursorPosition = e.target.selectionStart; setTimeout(() => { e.target.setSelectionRange(cursorPosition, cursorPosition); }, 0); };
解决方案
问题核心是React受控组件的重新渲染会重置光标位置:当AddModuleState更新state后,组件重新渲染,textarea会根据新的value值重新渲染,光标被默认重置到末尾。之前的setTimeout因执行时机不确定,偶尔失效。
步骤1:给textarea添加ref
通过ref获取textarea的DOM元素,方便后续操作:
React.createElement('textarea', { ref: (el) => { this.textareaRef = el; }, // 新增ref name: 'SpecialInstruction', id: 'rad_SpecialInstruction', value: this.props.stateobj.SpecialInstruction, onFocus: (event) => { const currentValue = event.target.value; // 保留原有注释代码 }, onChange: this.handleOrderChange, className: 'form-control', maxLength: 512, style: { fontSize: '12px !important' }, })
步骤2:在onChange中保存光标位置
将光标位置保存到组件实例属性中,避免在重新渲染时丢失:
_this.handleOrderChange = function (e) { // 保存当前光标位置到组件实例 _this.cursorPosition = e.target.selectionStart; // 更新state保存内容 _this.props.AddModuleState(_defineProperty({}, e.target.name, e.target.value), "RAD"); };
步骤3:在componentDidUpdate中恢复光标
利用React生命周期,在组件更新完成后(确保textarea已重新渲染)恢复光标位置:
componentDidUpdate(prevProps) { // 仅当SpecialInstruction内容变化时,恢复光标 if (this.props.stateobj.SpecialInstruction !== prevProps.stateobj.SpecialInstruction && this.cursorPosition !== undefined) { this.textareaRef.setSelectionRange(this.cursorPosition, this.cursorPosition); // 重置光标位置,避免后续不必要的恢复 this.cursorPosition = undefined; } }
这种方法通过明确的生命周期时机控制光标恢复,比setTimeout更可靠,能彻底解决光标跳转问题,同时保证内容正常保存。
内容的提问来源于stack exchange,提问作者Dragut
相关产品推荐
相关产品推荐

