Let's suppose that you want to indent a line on a <textarea></textarea>
in React.
Here is the skeleton:
jsximport React, { useState } from 'react'; const TextareaInput = () => { const [text, setText] = useState({value: ''}); const handleText = (e) => setText({value: e.target.value}); return( <textarea onChange = {handleText} value = {text.value} /> ) } export default TextareaInput;
Add 2 properties to the text
variable to control the position of the caret and the target element (textarea).
Furthermore, create a handleTab
function and useEffect
to accomplish the following:
jsximport React, { useEffect, useState } from 'react'; const TextareaInput = ({spaces = 4}) => { const [text, setText] = useState({value: '', caret: -1, target: null}); useEffect(() => { if(text.caret >= 0){ text.target.setSelectionRange(text.caret + spaces, text.caret + spaces); } }, [text]); const handleTab = (e) => { let content = e.target.value; let caret = e.target.selectionStart; if(e.key === 'Tab'){ e.preventDefault(); let newText = content.substring(0, caret) + ' '.repeat(spaces) + content.substring(caret); setText({value: newText, caret: caret, target: e.target}); } } const handleText = (e) => setText({value: e.target.value, caret: -1, target: e.target}); return( <textarea onChange = {handleText} onKeyDown = {handleTab} value = {text.value} /> ) } export default TextareaInput;
The useEffect
Hook is triggered after a text update, but the caret is repositioned only if it's equal or greater than 0.
Thus, the caret will be repositioned only after a handleTab
execution.
Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.