Reputation: 234
I went to the official reactjs website and found this
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
If i am replacing
componentDidMount() {
window.addEventListener('keydown', this.keypressed);
}
with this
useEffect(() => {
window.addEventListener('keydown', keypressed);
},[]);
it should be an issue, right?
But when I am using useEffect and pressing the key very fast then it's breaking the site which is not happening in the class-based components.
This is my class-based component code which is working fine and not breaking the site
/* eslint-disable eqeqeq */
import React, { Component } from 'react';
import data from './content/data';
import List from './List';
import Image from './Image';
import '../style/App.sass';
export class App extends Component {
state = {
currentIndex: 0,
};
componentDidMount() {
window.addEventListener('keydown', this.keypressed);
}
keypressed = (e) => {
let { currentIndex } = this.state;
if (e.keyCode == '38' || e.keyCode == '40') e.preventDefault();
if (e.keyCode == '38') {
this.setState({
currentIndex: (currentIndex - 1 + data.length) % data.length,
});
}
if (e.keyCode == '40') {
this.setState({
currentIndex: (currentIndex + 1) % data.length,
});
}
};
sendIndex = (i) =>
this.setState({
currentIndex: i,
});
render() {
return (
<div className="container0">
<List
currentIndex={this.state.currentIndex}
sendIndex={this.sendIndex}
/>
<Image currentIndex={this.state.currentIndex} />
</div>
);
}
}
export default App;
This is my function-based component code
/* eslint-disable eqeqeq */
import React, { useState, useEffect } from 'react';
import data from './content/data';
import List from './List';
import Image from './Image';
import '../style/App.sass';
const App = () => {
const [currentIndex, setCurrentIndex] = useState(0);
const keypressed = (e) => {
if (e.keyCode == '38' || e.keyCode == '40') e.preventDefault();
if (e.keyCode == '38')
setCurrentIndex((currentIndex - 1 + data.length) % data.length);
if (e.keyCode == '40')
setCurrentIndex((currentIndex + 1) % data.length);
};
const sendIndex = (i) => setCurrentIndex(i);
// window.addEventListener('keydown', keypressed);
useEffect(() => {
window.addEventListener('keydown', keypressed);
}, []);
return (
<div className="container0">
<List currentIndex={currentIndex} sendIndex={sendIndex} />
<Image currentIndex={currentIndex} />
</div>
);
};
export default App;
Please tell me what I am doing wrong.
Upvotes: 1
Views: 235
Reputation: 53914
For unknown reason you disabled eslint
errors (/* eslint-disable */
), with them you would be suggested to fix the closure on staled value of currentIndex
state.
Possible fix is passing a callback to useState
setter:
const App = () => {
const [currentIndex, setCurrentIndex] = useState(0);
const sendIndex = (i) => setCurrentIndex(i);
useEffect(() => {
const keypressed = (e) => {
if (e.keyCode == "38" || e.keyCode == "40") e.preventDefault();
if (e.keyCode == "38")
setCurrentIndex(
(prevIndex) => (prevIndex - 1 + data.length) % data.length
);
if (e.keyCode == "40")
setCurrentIndex((prevIndex) => (prevIndex + 1) % data.length);
};
window.addEventListener("keydown", keypressed);
}, []);
return (
<div className="container0">
<List currentIndex={currentIndex} sendIndex={sendIndex} />
<Image currentIndex={currentIndex} />
</div>
);
};
Upvotes: 2