简体   繁体   English

反应状态未在关键事件上更新

[英]React State not updating on key event

I'm running into an issue that I can't quite figure out.我遇到了一个我无法弄清楚的问题。 I'm building a Wordle clone, the state seems to be updating on some events and not on others, and I can't quite track down why.我正在构建一个 Wordle 克隆,状态似乎正在更新某些事件而不是其他事件,我无法完全找出原因。

I have a Keyboard<\/code> component, which takes handleKeyClick<\/code> as a prop from the parent component, and that is attached to two event handlers.我有一个Keyboard<\/code>组件,它将handleKeyClick<\/code>作为父组件的道具,并附加到两个事件处理程序。

Parent Component父组件<\/h2>
import { Box, Divider, Grid, Typography } from "@mui\/material"; import { useState, useEffect, useCallback } from 'react'; import Keyboard from "..\/Keyboard"; import { v4 as uuid } from 'uuid' import WordleNotifbar from "..\/WordleNotifBar"; import Loading from "..\/Utils\/Loading"; import { IGuessState } from "..\/..\/types"; interface IGuessGridProps { addGuess: Function, guesses: any, answer: any } const GuessGrid = (props: IGuessGridProps) => { const { addGuess, guesses, answer } = props; let [notif, setNotif] = useState<boolean>(false); const [guess, setGuess] = useState<string[]>([]); const styles = { input: { border: ".5px solid white", height: "50px", display: "flex", borderRadius: "5px", justifyContent: "center", alignItems: "center", backgroundColor: "", color: "white", }, container: { minWidth: "300px", width: "30%", maxWidth: "450px", margin: "0 auto", marginTop: "15px", }, } \/\/ In the parent component, I have defined the function I'm passing in as a prop as such: const handleAddCharacter = (char: string) => { setGuess([...guess, char]) } \/\/ Not fully implemented yet const handleBackspace = (e: MouseEvent): void => { e.preventDefault(); setGuess([...guess]) } const handleSubmit = (): void => { let word = guess.join('') if (word.length === answer.length) { addGuess(word.toLowerCase()) setGuess([]); } else { setNotif(true); setTimeout(() => { setNotif(false); }, 1000) } } if (answer) { return <> <Divider \/> <Grid container sx={styles.container} > {answer.split('').map((_: string, index: number) => { return (<Grid item xs={12 \/ answer.length} sx={styles.input} key={uuid()}> <Box> <Typography> {guess[index]} <\/Typography> <\/Box> <\/Grid>) })} <\/Grid> <Keyboard guesses={guesses} answer={answer} handleKeyClick={handleAddCharacter} handleBackspace={handleBackspace} submitFunc={handleSubmit} \/> {notif ? <WordleNotifbar message="Not Enough Characters" duration={1000} \/> : ""} <\/>; } else { return <Loading \/> } }; export default GuessGrid;<\/code><\/pre>

Keyboard Component键盘组件<\/h2>
import { Box, Grid, SxProps, Theme, Typography } from "@mui\/material"; import { useCallback, useEffect, useState } from 'react'; import { v4 as uuid } from 'uuid'; import BackspaceIcon from '@mui\/icons-material\/Backspace'; import React from "react"; interface IKeyboardProps { guesses: string[], answer: string, handleKeyClick: any, submitFunc: any, handleBackspace: any } const Keyboard = (props: IKeyboardProps) => { const { guesses, answer, handleKeyClick, submitFunc, handleBackspace } = props const [guessedLetters, setGuessedLetters] = useState<string[]>(); const topRow = 'qwertyuiop'.toUpperCase().split(''); const middleRow = 'asdfghjkl'.toUpperCase().split(''); const bottomRow = 'zxcvbnm'.toUpperCase().split(''); const allKeys = topRow.concat(middleRow.concat(bottomRow)); \/\/ When the component is initialized, I am establishing an event listener in the window for the key press events. useEffect(() => { window.addEventListener('keypress', handlePhysicalKeyPress) }, []) useEffect(() => { const allGuessedCharacters = guesses.join('').split(''); const uniqueGuessedCharacters = allGuessedCharacters.filter((val: string, index: number, self) => self.indexOf(val) === index) setGuessedLetters(uniqueGuessedCharacters); }, [guesses]) const handleVirtualKeyPress = (e: any) => { handleKeyClick(e.target.textContent) } const handlePhysicalKeyPress = (e: KeyboardEvent) => { e.preventDefault() if (allKeys.includes(e.key.toUpperCase())) { handleKeyClick(e.key.toUpperCase()); } } const genKeyStyles = (character: string, _: number): SxProps<Theme> => { character = character.toLowerCase() const styles = { width: character === "bs" || character === "enter" ? "63px" : "33px", marginX: "1px", marginY: "1px", borderRadius: "5px", height: "50px", color: "black", textAlign: "center", backgroundColor: "#DDD", display: "flex", justifyContent: "center", alignItems: "center", }; if (guessedLetters) { if (answer.indexOf(character) >= 0 && guessedLetters.indexOf(character) >= 0) { styles.backgroundColor = "green" } else if (answer.indexOf(character) < 0 && guessedLetters.indexOf(character) >= 0) { styles.backgroundColor = "#777" } } return styles } return <Box sx={{ display: "flex", flexDirection: "column", justifyContent: "center", marginTop: "10px", }}> <Box sx={{ display: "flex", justifyContent: "center" }}> {topRow.map((letter: string, index: any) => { return ( <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}> <Typography key={uuid()}>{letter}<\/Typography> <\/Box> ) })} <\/Box> <Box sx={{ display: "flex", justifyContent: "center" }}> {middleRow.map((letter: string, index: any) => { return ( <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}> <Typography key={uuid()}>{letter}<\/Typography> <\/Box> ) })} <\/Box> <Box sx={{ display: "flex", justifyContent: "center" }}> <Box sx={genKeyStyles("enter", 1)} key={uuid()} onClick={submitFunc}> <Typography key={uuid()}>enter<\/Typography> <\/Box> {bottomRow.map((letter: string, index: any) => { return ( <Box sx={genKeyStyles(letter, index)} key={uuid()} onClick={handleVirtualKeyPress}> <Typography key={uuid()}>{letter}<\/Typography> <\/Box> ) })} <Box sx={genKeyStyles("bs", 1)} key={uuid()} onClick={handleBackspace}> <Typography key={uuid()}><BackspaceIcon \/><\/Typography> <\/Box> <\/Box> <\/Box> }; export default Keyboard;<\/code><\/pre>

What happens is that the virtual key press seems to update the state properly, but the physical keypress seems to reset the state back to an empty array.发生的情况是虚拟按键似乎正确更新了状态,但物理按键似乎将状态重置回空数组。 I can't really figure out a good reason why this is happening.我真的无法弄清楚为什么会发生这种情况。 Any thoughts?有什么想法吗? I appreciate your help in advance!我提前感谢您的帮助!

Link to Live Application<\/a> 链接到实时应用程序<\/a>

"

When you do:当你这样做时:

    useEffect(() => {
        window.addEventListener('keypress', handlePhysicalKeyPress)
    }, [])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM