Estoy desarrollando un área de texto que contiene algunas palabras específicas (por ejemplo, pueden comenzar/terminar con "%": %QWERTY%). Quiero que estas palabras tengan un color diferente (por ejemplo, verde) y que el área de texto siga siendo editable. He probado algunas soluciones pero no funcionan como esperaba, por eso me gustaría preguntarle a la comunidad cómo implementar un área de entrada de texto.
Mi código está aquí https://codesandbox.io/s/festive-cache-sshmjd?file=/src/TagsInput.js
En las entradas 1 y 2, clasifiqué palabras y usé map() para mostrarlas en etiquetas, sin embargo, se convirtieron en entradas separadas, no se combinaron en una sola
En la tercera entrada, implementé a para la palabra especial, pero esta es una cadena fija y no sé cómo implementarla como una variable de estado para detectar cualquier cambio en el área de entrada.
¿Alguien podría revisar mi código y ayudar?
Esto funciona, colorea la palabra objetivo una vez que la entrada ya no está enfocada.
Funciona guardando el texto en estado onBlur, separando la cadena cada vez que ve la palabra de destino "rojo".
// src/components/TagsInput.js import React, { useState } from "react"; function TagsInput() { const [tags, setTags] = useState([]); const todoList = [ { title: "item 1", isDone: false }, { title: "item 2", isDone: true }, ]; function handleKeyDown(e) { if (e.key !== "Enter") return; const value = e.target.value; if (!value.trim()) return; setTags([...tags, value]); e.target.value = ""; console.log("tags: " + tags); } function removeTag(index) { setTags(tags.filter((el, i) => i !== index)); } const onCodeChange = (event) => { console.log("onCodeChange: " + event.currentTarget.textContent); }; function TodoItem({ title, isDone }) { return ( <span contentEditable="true" style={{ color: isDone ? "green" : "red" }} value={title} onInput={onCodeChange} > {title} </span> ); } function Todo(props) { const todoList = props.todoList.map((el) => ( <TodoItem key={el.id} title={el.title} isDone={el.isDone} /> )); return <p className="tags-input-container">{todoList}</p>; } function ColorfulText({ children }) { return <span style={{ color: "green" }}>{children}</span>; } const [text, setText] = useState(["Your test sentence"]); const targetWord = "red"; // used to split the text at target word but keep the target word // in the returned array const regex = new RegExp(`(${targetWord})`); return ( <React.Fragment> <div className="tags-input-container"> {tags.map((tag, index) => ( <div className="tag-item" key={index}> <span className="text">{tag}</span> <span className="close" onClick={() => removeTag(index)}> × </span> </div> ))} <input onKeyDown={handleKeyDown} type="text" className="tags-input" placeholder="Type something and Press Enter" /> </div> <div> <code contentEditable="true" suppressContentEditableWarning={true}> {tags.map((tag) => { <span style={{ color: "orange" }}>{tag}</span>; })} </code> </div> <Todo todoList={todoList} /> <div> <p contentEditable="true" style={{ fontSize: "2rem" }} onBlur={(e) => { setText([...e.target.textContent.split(regex)]); }} > {text.map((words) => { if (words === targetWord) { return <ColorfulText>{words}</ColorfulText>; } else { return words; } })} </p> </div> </React.Fragment> ); } export default TagsInput;