J'ai une zone de texte dans React que je veux transformer en un "bloc-notes". Ce qui signifie que je veux que la touche "tab" soit en retrait au lieu de se défaire. J'ai regardé cette réponse , mais je n'arrive pas à le faire fonctionner avec React. Voici mon code:
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}/>
)
}
Lorsque j'exécute ce code, même si j'appuie sur la touche "tab" au milieu de la chaîne, mon curseur apparaît toujours à la fin de la chaîne. Quelqu'un sait comment régler correctement la position du curseur?
Vous devez changer la position du curseur après l'état a été mis à jour (setState()
ne mute pas immédiatement this.state
)
Pour ce faire, vous devez envelopper this.refs.input.selectionStart = this.refs.input.selectionEnd = start + 1;
dans une fonction et passez-le comme deuxième argument à setState
(rappel).
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
});
}
}
Voici une solution dans une architecture de type crochets. Ma recommandation est de changer la zone de texte value
et selectionStart
immédiatement lors de l'insertion des onglets.
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}
/>
)
}