Измените положение курсора в текстовом поле с помощью React
У меня есть текстовое поле в React, которое я хочу превратить в "блокнот". Это означает, что я хочу, чтобы клавиша "tab" была отступом, а не сфокусирована. Я посмотрел на этот ответ, но я не могу заставить его работать с React. Вот мой код:
handleKeyDown(event) {
if (event.keyCode === 9) { // tab was pressed
event.preventDefault();
var val = this.state.scriptString,
start = event.target.selectionStart,
end = event.target.selectionEnd;
this.setState({"scriptString": val.substring(0, start) + '\t' + val.substring(end)});
// This line doesn't work. The caret position is always at the end of the line
this.refs.input.selectionStart = this.refs.input.selectionEnd = start + 1;
}
}
onScriptChange(event) {
this.setState({scriptString: event.target.value});
}
render() {
return (
<textarea rows="30" cols="100"
ref="input"
onKeyDown={this.handleKeyDown.bind(this)}
onChange={this.onScriptChange.bind(this)}
value={this.state.scriptString}/>
)
}
Когда я запускаю этот код, даже если я нажимаю клавишу "tab" в середине строки, мой курсор всегда появляется в конце строки. Кто-нибудь знает, как правильно установить позицию курсора?
Ответы
Ответ 1
Вы должны изменить позицию курсора после обновления состояния (setState()
не сразу мутирует this.state
)
Для этого вам необходимо обернуть this.refs.input.selectionStart = this.refs.input.selectionEnd = start + 1;
в функции и передать ее как второй аргумент setState
(обратный вызов).
handleKeyDown(event) {
if (event.keyCode === 9) { // tab was pressed
event.preventDefault();
var val = this.state.scriptString,
start = event.target.selectionStart,
end = event.target.selectionEnd;
this.setState(
{
"scriptString": val.substring(0, start) + '\t' + val.substring(end)
},
() => {
this.refs.input.selectionStart = this.refs.input.selectionEnd = start + 1
});
}
}
jsfiddle
Ответ 2
Здесь решение в архитектуре стиля крючков. Моя рекомендация состоит в том, чтобы изменить value
textarea и selectionStart
немедленно при вставке вкладки.
import React, { useRef } from "react"
const CodeTextArea = ({ onChange, value, error }) => {
const textArea = useRef()
return (
<textarea
ref={textArea}
onKeyDown={e => {
if (e.key === "Tab") {
e.preventDefault()
const { selectionStart, selectionEnd } = e.target
const newValue =
value.substring(0, selectionStart) +
" " +
value.substring(selectionEnd)
onChange(newValue)
if (textArea.current) {
textArea.current.value = newValue
textArea.current.selectionStart = textArea.current.selectionEnd =
selectionStart + 2
}
}
}}
onChange={e => onChange(e.target.value)}
value={value}
/>
)
}