Estoy creando un juego como wordle y, para hacer esto, cuando el usuario escribe una carta, la aplicación debe enfocar la siguiente entrada. No puedo hacer esto, y no sé por qué.
const GameLine = (props) => { const lineIndex = props.index; const checkTry = () => { const userGuess = firstLetter + ' ' + secondLetter + ' ' + thirdLetter + ' ' + fourthLetter + ' ' + fifthLetter; console.log(userGuess); } const [firstLetter, setFirstLetter] = useState(null); const [secondLetter, setSecondLetter] = useState(null); const [thirdLetter, setThirdLetter] = useState(null); const [fourthLetter, setFourthLetter] = useState(null); const [fifthLetter, setFifthLetter] = useState(null); const handleNextInput = (e) => { console.log("ID atual: " + e.target.id); const fieldName = e.target.id.split('-')[1]; const nextSibiling = document.getElementById(`box${lineIndex}-${parseInt(fieldName) + 1}`); console.log(nextSibiling); if(nextSibiling !== null){ nextSibiling.focus(); } } return ( <BoxesDiv> <Box1 type="text" id={ `box${lineIndex}-1`} onChange={(e) => { handleNextInput(e); setFirstLetter(e.target.value)}} value={firstLetter} /> <Box2 type="text" id={ `box${lineIndex}-2`} onChange={(e) => setSecondLetter(e.target.value)} value={secondLetter} onKeyPress={(e)=>handleNextInput(e)}/> <Box3 type="text" id={ `box${lineIndex}-3`} onChange={(e) => { handleNextInput(e); setThirdLetter(e.target.value)}} value={thirdLetter} /> <Box4 type="text" id={ `box${lineIndex}-4`} onChange={(e) => { handleNextInput(e); setFourthLetter(e.target.value)}} value={fourthLetter} /> <Box5 type="text" id={ `box${lineIndex}-5`} onChange={(e) => setFifthLetter(e.target.value)} value={fifthLetter} onKeyPress={ (e)=>{ if(e.key === "Enter"){checkTry()} } }/> </BoxesDiv> ); }Estoy tratando de obtener la siguiente entrada con id y uso Element.focus(), pero no pasa nada. ¿Alguien podría ayudarme a encontrar dónde está mi error?
Gracias
Debe llamar a la función handleNextInput para el segundo cuadro. Creo que podría activar la función KeyUp para handleNextInput .
<Box2 onKeyUp={(e)=>handleNextInput(e)} ... />La forma en que React accede a los elementos es usar refs . Puede crear una matriz de referencias inicialmente y asignarlas a las entradas. Agregue un detector de eventos keyup para actualizar el enfoque de entrada a la siguiente entrada.
Prueba como a continuación.
import { useState, createRef, useEffect } from "react"; const GameLine = (props) => { const lineIndex = props.index; // number of inputs const numerOfInputs = props?.numerOfInputs || 5; // create a array of refs const [inputRefsArray] = useState(() => Array.from({ length: numerOfInputs }, () => createRef()) ); // state for current input index const [currentIndex, setCurrentIndex] = useState(0); // save letters in a array where each entry in the array refers to an input const [letters, setLetters] = useState(() => Array.from({ length: numerOfInputs }, () => "") ); const handleKeyPress = () => { setCurrentIndex((prevIndex) => { // calculate the next input index, next input after the final input will be again the first input. you can change the logic here as per your needs const nextIndex = prevIndex < numerOfInputs - 1 ? prevIndex + 1 : 0; const nextInput = inputRefsArray?.[nextIndex]?.current; nextInput.focus(); nextInput.select(); return nextIndex; }); }; useEffect(() => { // focus the firs iput initially if (inputRefsArray?.[0]?.current) { inputRefsArray?.[0]?.current?.focus(); } // add the event listener for keyup keyboard event window.addEventListener("keyup", handleKeyPress, false); // remove the event listener when the component unmounts return () => { window.removeEventListener("keyup", handleKeyPress); }; }, []); return ( <div> {inputRefsArray.map((ref, index) => { return ( <input ref={ref} type="text" id={`box${index}-1`} onChange={(e) => { const { value } = e.target; setLetters((letters) => letters.map((letter, letterIndex) => letterIndex === index ? value : letter ) ); }} onClick={(e) => { setCurrentIndex(index); e.target.select(); }} value={letters[index]} max={"1"} /> ); })} </div> ); }; export default GameLine;