I am not sure why I am getting this error, I have been looking online to find an answer but I cannot seem to figure it out. The error is coming from when I am trying to change the state of a state variable when the key 'Enter' is pressed. I am still new to react so any help would be greatly appreciated!!
Here is the error message
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
20 |
21 | case "Enter":
22 | if(timerState === false){
> 23 | setTimerState(true);
| ^ 24 | }
25 | break;
26 |
Here is the file in question
import React, { useState, useEffect } from 'react';
import { words } from "./words.json";
import TypingTest from './components/TypingTest';
import SignInModal from './components/SignInModal';
import TitleBar from './components/TitleBar';
import Timer from './components/Timer';
import './App.css';
import { ThemeProvider } from 'styled-components';
function App() {
const [index, setIndex] = useState(0);
const [showSignIn, setShowSignIn] = useState(false);
const [timerState, setTimerState] = useState(false);
const onKeyPress = (event) => {
console.log("Current key: ", event.key);
switch (event.key) {
case "Enter":
if(timerState === false){
setTimerState(true);
}
break;
case "Backspace":
break;
default:
if(event.key === words[index]){
setIndex((index) => index 1);
}
break;
}
};
const openSignIn = () => {
setShowSignIn(prev => !prev);
};
useEffect(() => {
document.addEventListener('keydown', onKeyPress);
return () => {
document.removeEventListener('keydown', onKeyPress);
};
}, [index])
return (
<div className="App">
<TitleBar openSignIn={openSignIn} />
<header className="App-header">
</header>
<div className="landing">
{/* <Timer /> */}
<TypingTest timerState={timerState} words={words} index={index}/>
<button onClick = {() => setIndex(0)}>reset</button>
<SignInModal showSignIn={showSignIn} setShowSignIn={setShowSignIn} />
</div>
</div>
);
}
export default App;
CodePudding user response:
First of all you have to turn off your useEffect
. Occur only once. You can access your current state value within setState
setState(currentState => {
return currentState;
});
The keydown
, and keypress
, and keyup
events cause the component to re-render
I know a solution to this problem, but I'm not sure it is the main solution, but it solves the problems
You can define your states inside useEffect
as a variable and change their value
useEffect(() => {
let timerState;
const onKeypress = (e) => {
// do anything
}
document.addEventListener("keypress", onKeypress);
return () => {
document.removeEventListener("keypress", onKeypress);
}
}, []);
CodePudding user response:
Adding a listener inside a useEffect
which has dependencies means any time those variables in the dependency array change, you are adding another listener. To set a listener when the component mounts, put the addEventListener
method in a useEffect
that has an empty (or no) dependency array.
useEffect(() => {
document.addEventListener('keydown', onKeyPress);
return () => {
document.removeEventListener('keydown', onKeyPress);
};
}, [])