I'm creating a Tetras game with react, all was working well and executing as expected till is added a Keyboard EventListener which majorly listens for the the Right and Left arrow key to move the component The Problem is, every time I call setState() in the function i assigned to the event it keeps repeating the same setState() function, without it even rendering the component, as a result i get the "Maximum update depth exceeded" Error. the code for my component:
class App extends React.Component {
constructor () {
super()
this.state = {
allBlocks: [],
allBlockClass: []
}
setInterval(this.newBlock, 5000)
document.addEventListener('keyup', this.userInput)
}
userInput = e => {
switch (e.key) {
case 'ArrowLeft': {
this.moveLeft()
break
}
case 'ArrowRight': {
// this.moveRight()
break
}
default: {
console.log('either left or right key')
}
}
}
moveLeft = () => {
this.setState(prevState => {
const old_state = Object.assign([], prevState.allBlocks)
let newBlocksClass = prevState.state.allBlockClass
const new_state = old_state.map((blockData, index) => {
if (blockData.active) {
blockData.x_axis -= BLOCK_INCREMENT
if (!(index > this.state.allBlockClass.length - 1)) {
newBlocksClass[index].moveBlockLeft(BLOCK_INCREMENT)
}
}
return blockData
})
return { allBlocks: new_state, allBlockClass: newBlocksClass }
})
}
newBlock = () => {
let positions = generateBlockPositions()
const blockData = {
positions: positions,
active: true,
x_axis: axis_props.Min_x_axis + BLOCK_INCREMENT * randomInt(3),
y_axis: axis_props.Min_y_axis + BLOCK_INCREMENT
}
this.setState(prevState => {
let new_state = [...prevState.allBlocks]
new_state.push(blockData)
return { allBlocks: new_state }
})
}
render () {
this.resetValues()
return (
<div className='myBody'>
{this.state.allBlocks.map((blockData, index) => {
this.numberOfBlock++
return (
<CreateBlockStructure
x_axis={blockData.x_axis}
y_axis={blockData.y_axis}
positions={blockData.positions}
key={index}
id={index}
run={blockData.active}
shouldRun={this.shouldRun}
inActivate={this.inActivate}
addBlockStructure={this.addBlockStructure}
/>
)
})}
<button onClick={this.moveLeft}>Move left</button>
<button onClick={this.moveLeft}>Move Right</button>
</div>
)
}
You can checkout the full code for this project
The moveLeft() works properly outside the Keyevent function but when i call it with any other event handler it infinitly calls the setState() method e.g the MoveLeft button
the moveBlockLeft() is just a simple func in another component
moveBlockLeft(by){
this.setState((prevState)=> {
return {x_axis: prevState.x_axis - by}
})
}
Please i've really spent a lot of time debugging this bug, i have no idea what is going on Thanks in advance
you are trying to set a value of state variable while update value of another state variable which is why it is ending up into an infinite loop.
Basically in your moveLeft function while setting state you are called moveBlockLeft which is again setting state.
To fix this call moveBlockLeft outised the setState inside your moveLeft.