Как заменить компоненты на основе классов на крючки в react

#javascript #html #css #reactjs #react-native

Вопрос:

Я зашел на официальный сайт reactjs и нашел это

   // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });
 

Если я заменяю

 componentDidMount() {
        window.addEventListener('keydown', this.keypressed);
    }
 

с этим

 useEffect(() => {
        window.addEventListener('keydown', keypressed);
    },[]);
 

это должно быть проблемой, верно?

Но когда я использую useEffect и очень быстро нажимаю клавишу, это нарушает сайт, чего не происходит в компонентах, основанных на классах.

Это мой код компонента на основе классов, который работает нормально и не нарушает работу сайта

 /* 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;
 

Это мой функциональный код компонента

 /* 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;
 

Пожалуйста, скажите мне, что я делаю не так.

Комментарии:

1. Вы получаете какие-либо ошибки в консоли браузера?

2. @Kundansingchouhan Нет, я не получаю никаких ошибок

Ответ №1:

По неизвестной причине вы отключили eslint функции errors ( /* eslint-disable */ ), с их помощью вам будет предложено исправить закрытие на заблокированном значении currentIndex состояния.

Возможное исправление-передача обратного useState вызова сеттеру:

 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>
  );
};