1

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.

2
  • Are you getting any errors in the browser's console? Commented Jul 3, 2021 at 16:09
  • @KundanSinghChouhan No, I am not getting any error Commented Jul 3, 2021 at 16:11

1 Answer 1

2

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>
  );
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.