1

我正在创建一个类似 wordle 的游戏,为此,当用户写信时,应用程序应该关注下一个输入。我不能这样做,我不知道为什么。

    
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>  
    );
}

我正在尝试使用 id 获取下一个输入并使用 Element.focus(),但没有任何反应。有人可以帮我找出我的错误在哪里吗?

谢谢

4

2 回答 2

0

您应该为第二个框调用handleNextInput函数。我认为您可以为handleNextInput 使用onKeyUp 函数。

<Box2 onKeyUp={(e)=>handleNextInput(e)} ... />
于 2022-02-16T17:47:55.117 回答
0

React 访问元素的方式是使用refs。您最初可以创建一个引用数组并将它们映射到输入。添加keyup事件侦听器以将输入焦点更新到下一个输入。

尝试如下。

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;

编辑 ecstatic-franklin-m94ci0

于 2022-02-16T17:55:52.067 回答