Не удается вызвать функцию из обработчика событий keyDown в приложении ReactJS

#reactjs #function #typeerror #addeventlistener #onkeydown

Вопрос:

Я возвращаюсь к приложению для слайд-шоу, над которым работал в прошлом году. У меня есть функции prevSlide и nextSlide, настроенные таким образом, чтобы триггер срабатывал при нажатии кнопки, но я также хочу поддерживать навигацию по клавишам со стрелками (и, возможно, функцию прокрутки мобильного экрана в будущем).

Я настроил функции componentDidMount/ComponentDidUnmount для регистрации поддержки нажатия клавиш для обработчиков событий handleKeyDown, и мой обработчик событий handleKeyDownRight работает, если он просто запускает текст предупреждения. К сожалению, если я попытаюсь вызвать свою функцию nextSlide из функции handleKeyDownRight, React выдаст следующую ошибку: «Ошибка типа: this.nextSlide не является функцией».

Какие настройки я могу внести, чтобы handleKeyDownRight запускал nextSlide (), как это делает нажатие кнопки «далее»?

 import React, {Component} from 'react';
import '../Cantiche.scss';

import Card from '../Card/Card';
import data from '../../../data/data';

class Inferno extends Component {
        state = {
          book: data.inferno,
          slide: data.inferno[0]
        }

        componentDidMount = () => {
          window.addEventListener('keydown', this.handleKeyDownRight);
        }

        prevSlide = () => {
          const newIndex = this.state.slide.index-1;
          this.setState({
            slide: data.inferno[newIndex]
          })
        }

      nextSlide = () => {
        const newIndex = this.state.slide.index 1;
        this.setState({
          slide: data.inferno[newIndex]
        })
      }

      handleKeyDownRight(event) {
        if(event.keyCode === 39){
          alert('Right arrow key');
          this.nextSlide(); //Throws error: "TypeError: this.nextSlide is not a function"
        }
      }

      componentWillUnmount = () => {
        window.addEventListener('keydown', this.handleKeyDownRight);
      }

    render () {
        const {slide} = this.state;

        let cards = (
            <div className={`cards-slider active-slide-${slide.index}`} >
              <div className="cards-slider-wrapper" style={{
                'transform': `translateX(-${slide.index*(100/this.state.book.length)}%)`
              }}>
                {
                  this.state.book.map(slide => <Card key={slide._id} slide={slide} />)
                }
              </div>
            </div>
        )

        return (
            <div className="card-container">
              <h1>Inferno</h1>
              <div className="buttons" onKeyDown={this.handleKeyDownRight}>
                <button 
                  onClick={() => this.prevSlide()} 
                  disabled={slide.index === 0}
                >Prev</button>
                <button 
                  onClick={() => this.nextSlide()} 
                  disabled={slide.index === data.inferno.length-1}
                >Next</button>
              </div>
              {cards}
          </div>
        );
    }
}

export default Inferno;

 

Ответ №1:

Пожалуйста, попробуйте написать hadleKeyDownRight как функцию со стрелкой, чтобы она была привязана к вашему компоненту, как и другие подобные функции:

   handleKeyDownRight = (event) => {
    if(event.keyCode === 39){
      alert('Right arrow key');
      this.nextSlide(); //Throws error: "TypeError: this.nextSlide is not a function"
    }
 

Вам не нужно регистрировать прослушиватели событий в React. Это будет обрабатываться React, и, кроме того, события в React работают по-другому. Об этом вы можете прочитать в документах: https://reactjs.org/docs/handling-events.html

Если это вам не поможет, пожалуйста, напишите в комментарии, что пошло не так.

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

1. @Энди, добро пожаловать, в этих случаях вы можете одобрить ответы, чтобы все могли видеть, что, по крайней мере, этот ответ был решением этого вопроса. 🙂

Ответ №2:

Вот рабочий код для функции handleKeyDown; Одна функция с соответствующими условными операторами может обрабатывать навигацию со стрелками вправо и влево. Обратите внимание, что я настроил условные обозначения так, чтобы они не срабатывали, если значение slide.index равно 0 (для prevSlide) или отсутствует (следующий слайд).

 handleKeyDown = (event) => {
  if(event.keyCode === 39 amp;amp; this.state.slide.index !== data.inferno.length-1 ){
    this.nextSlide();
  } else if(event.keyCode === 37 amp;amp; this.state.slide.index !== 0){
    this.prevSlide();
  }
}

...

<div className="buttons" onKeyDown={this.handleKeyDown}>