Для вызова функции входа в систему Только один раз после нажатия клавиши «ввод»

Я работаю над функцией входа в систему прямо сейчас. Я поместил свою функцию enterKey на вход, и моя цель — вызвать функцию входа в систему, когда пользователь нажимает клавишу ввода. Он отлично работает, если в области ввода ничего нет, однако я обнаружил, что если у меня есть несколько символов в области ввода текста, функция будет вызываться несколько раз и выдавать несколько сообщений об ошибках. Например, если у меня есть N символов на входе, я получу (N+1) сообщений об ошибках после нажатия клавиши ввода. Вот мой код:

 enterKeyPress() {
    window.addEventListener("keypress", e => {
      if (e.keyCode === 13) {
        console.log('enter key pressed!'); // I will receive this msg (N+1) times when there're N characters in the input text area 
        e.preventDefault();
        this.loginUser(); // this is the login function I want to call after press enter key, but just once per press
      }
    });
  }
 render() {
    return(
      <Input
         type="password"
         placeholder="Password"
         onChange={e =>
            this.setState({ password: e.target.value })
         }
         onKeyPress={this.enterKeyPress()}
      />
    );
}

Кто-нибудь может мне с этим помочь?


person hikerE    schedule 12.04.2019    source источник
comment
вы добавляете прослушиватель событий каждый раз, когда нажимается клавиша   -  person Ronnie    schedule 13.04.2019
comment
^ Спасибо за ваши ответы, я очень ценю. Я думаю об удалении прослушивателя событий после вызова функции. Есть ли лучшее и простое решение?   -  person hikerE    schedule 13.04.2019


Ответы (3)


В этом случае прослушиватели событий не нужны.

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

enterKeyPress = (e) => {
    if (e.keyCode === 13) {
        console.log('enter key pressed!');
        e.preventDefault();
        this.loginUser();
    });
}

Преобразование enterKeyPress в функцию стрелки — это один из способов привязать функцию к компоненту. Другой вариант — привязать функцию к вашему конструктору или к вашей функции render, которая хорошо задокументирована в другом месте. Если вы уже связали функцию в своем конструкторе (вы не включили ее здесь), вы можете игнорировать эту часть.

Во-вторых, настройте свойство onKeyPress так, чтобы функция передавалась, а не вызывалась:

<Input
    type="password"
    placeholder="Password"
    onChange={e =>
        this.setState({ password: e.target.value })
    }
    onKeyPress={this.enterKeyPress}
/>

Также стоит отметить, что здесь есть еще одна общая ошибка JavaScript: использование анонимной функции обратного вызова в вашем прослушивателе событий. Используя анонимную функцию, вы позволяете одной и той же функции добавляться несколько раз, поскольку каждый раз генерируется другая ссылка на функцию. Это также означает, что вы не сможете удалить его позже, поскольку для этого вам потребуется ссылка на функцию.

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

handleKeyPress = (e) => {
    if (e.keyCode === 13) {
      console.log('enter key pressed!'); 
      e.preventDefault();
      this.loginUser();
    });
} 

componentDidMount() {
    window.addEventListener("keypress", this.handleKeyPress);
}

componentWillUnmount() {
    window.removeEventListener("keypress", this.handleKeyPress);
}
person Dylan Walker    schedule 13.04.2019

Из некоторого быстрого поиска в Google я думаю, что это может сделать то, что вам нужно:

enterKeyPress(e) {
    if (e.keyCode === 13) {
      console.log('enter key pressed!'); // I will receive this msg (N+1) times when there're N characters in the input text area 
      e.preventDefault();
      this.loginUser(); // this is the login function I want to call after press enter key, but just once per press
    });
}
render() {
    return(
      <Input
         type="password"
         placeholder="Password"
         onChange={e =>
            this.setState({ password: e.target.value })
         }
         onKeyPress={this.enterKeyPress}
      />
    );
}

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

person John Montgomery    schedule 13.04.2019
comment
Спасибо за ваш ответ, но я уже протестировал это решение, и оно выдало мне сообщение об ошибке, например, код ключа не определен. Итак, я думаю, мне все еще нужен прослушиватель событий. - person hikerE; 13.04.2019
comment
@hikerE Вы удалили скобки в конце функции? Как написано в вашем вопросе, вы не разрешаете передавать параметр события. - person John Montgomery; 13.04.2019
comment
Я немного запутался, вы имеете в виду круглые скобки перед точкой с запятой? Но это часть addeventlistener. - person hikerE; 13.04.2019
comment
@hikerE Нет, в onKeyPress={this.enterKeyPress}. Вот как все примеры, которые я нашел, использовали его. - person John Montgomery; 13.04.2019
comment
К сожалению, если я удалю круглые скобки, функция enterKeyPress не будет вызываться. - person hikerE; 13.04.2019

Как отметил @Ronnie в комментариях, вы добавляете новый прослушиватель событий каждый раз, когда функция onKeyPress запускается в компоненте, что вызывает проблемы. Поскольку событие onKeyPress уже передает event в качестве аргумента (аналогично событию onClick), вы можете получить доступ к keyCode оттуда.

Вы можете изменить свою функцию enterKeyPress на следующее:

enterKeyPress(e) {
    if (e.keyCode === 13) {
      console.log('enter key pressed!'); 
      e.preventDefault();
      this.loginUser();
    }
  }
person Claire Lin    schedule 13.04.2019