onKeyDown 이벤트가 React의 div에서 작동하지 않습니다.


92

React의 div에서 keyDown 이벤트를 사용하고 싶습니다. 나는한다:

  componentWillMount() {
      document.addEventListener("keydown", this.onKeyPressed.bind(this));
  }

  componentWillUnmount() {
      document.removeEventListener("keydown", this.onKeyPressed.bind(this));
  }      

  onKeyPressed(e) {
    console.log(e.keyCode);
  }

  render() {
    let player = this.props.boards.dungeons[this.props.boards.currentBoard].player;
    return (
      <div 
        className="player"
        style={{ position: "absolute" }}
        onKeyDown={this.onKeyPressed} // not working
      >
        <div className="light-circle">
          <div className="image-wrapper">
            <img src={IMG_URL+player.img} />
          </div>
        </div>
      </div>
    )
  }

잘 작동하지만 React 스타일에서 더 많이하고 싶습니다. 나는 시도했다

        onKeyDown={this.onKeyPressed}

구성 요소에. 하지만 반응하지 않습니다. 내가 기억하는 것처럼 입력 요소에서 작동합니다.

Codepen

어떻게하니?


개인적으로 나는 당신의 접근 방식을 좋아합니다. 이는 구성 요소의 범위를 벗어난 문서에 키 입력을 바인딩하는 좋은 방법처럼 보입니다. 특정 요소에 초점을 맞출 필요가 없습니다.
Daniel

답변:


159

React에서 div의 이벤트 를 수신 하려면 tabIndex 속성을 사용해야합니다 onKeyDown. 설정 tabIndex="0"은 핸들러를 실행해야합니다.


2
이것은 나쁘고 독단적 인 디자인처럼 보입니다. 컨테이너 요소에서 버블 링 이벤트를 처리하고 싶지만 해당 컨테이너 자체에 초점이 맞춰져서는 안되는 경우 어떻게해야합니까?
Will P.

1
이것은 나에게 더 많은 해킹이나 해결 방법처럼 보입니다. 주어진 div가 탭 순서를 유지해야 할 때가있을 수 있습니다.
Iwnnay

9
tabIndex={-1}대화 형이 아닌 요소로 작업하고 문서의 탭 순서를 변경하지 않으려는 경우에도 사용할 수 있습니다.
IliasT

1
div에 초점을 맞추려면 tabIndex를 설정해야합니다. tabIndex를 0,1, -1로 설정할 수 있습니다 ....하지만 그 전에 webaim.org/techniques/keyboard/tabindex 를 확인 하십시오. 프로그래밍 방식으로 조작하고 있으므로 -1로 설정하는 것이 좋습니다. .
Kavita

어떤 이유로 이것은 tabIndex가있는 div에 <input> 요소가있는 경우에만 작동합니다. 또는 집중할 수있는 다른 것. 다른 div에서만 여전히 캡처되지 않습니다. 이견있는 사람?
Flion

24

이런 식으로 작성해야합니다

<div 
    className="player"
    style={{ position: "absolute" }}
    onKeyDown={this.onKeyPressed}
    tabIndex="0"
  >

onKeyPressed바인딩되지 않은 경우 this화살표 기능을 사용하여 다시 작성하거나 구성 요소에 바인딩합니다 constructor.


2
죄송합니다. 나는 이것을 그냥 간과했다. 그러나 이것은 문제가 아닙니다. 여전히 작동하지 않습니다.
Michael

업데이트 된 답변. 키를 누르기 전에 div를 클릭하거나 포커스로 가져와야합니다.
Panther

내가했다. 작동하지 않습니다. 위의 코드를 업데이트했습니다. DOM 명령에서는 잘 작동하지만 React 스타일에서는 작동하지 않습니다.
Michael

작동하지 않는 것이 무엇인지 설명해 주시겠습니까? 함수가 호출되지 않거나 console.log아무것도 출력하지 않습니까?
Panther

함수가 호출되지 않습니다. codepen이 있습니다 : codepen.io/lafisrap/pen/OmyBYG . 그것은 275 선에 대한과 (307)
마이클

7

순수한 자바 스크립트에서 너무 많이 생각하고 있습니다. 해당 React 라이프 사이클 메소드에서 리스너를 제거하고 event.key대신 사용하십시오 event.keyCode(JS 이벤트 객체가 아니기 때문에 React SyntheticEvent입니다 ). 전체 구성 요소는 이렇게 간단 할 수 있습니다 (생성자에서 메서드를 바인딩하지 않았다고 가정).

onKeyPressed(e) {
  console.log(e.key);
}

render() {
  let player = this.props.boards.dungeons[this.props.boards.currentBoard].player;
  return (
    <div 
      className="player"
      style={{ position: "absolute" }}
      onKeyDown={this.onKeyPressed}
    >
      <div className="light-circle">
        <div className="image-wrapper">
          <img src={IMG_URL+player.img} />
        </div>
      </div>
    </div>
  )
}

그게 바로 제가 쓰고 싶었던 방법입니다. 그러나 지옥, 그것은 가지 않습니다. 다음은 codepen입니다 : codepen.io/lafisrap/pen/OmyBYG . 275 행을 주석 처리하면 키보드 입력 (커서 키)이 작동하지 않습니다. onKeyDown은 307 행에 있습니다.
Michael

keyCode 나는 문자를 반환하지 않기 때문에 커서 키에 사용합니다.
Michael

1
React는 Javascript 이벤트 객체를 사용하지 않으므로 keyCode 속성이 없습니다. 그 event객체는 React SyntheticEvent 입니다.
강철

@Michael 또한 div에서 키 이벤트를 트리거하는 방법을 완전히 확신하지 못하지만 핸들러 onClick대신에 소품을 사용 하여이 코드를 바이올린에 넣을 때 onKeyDown발생합니다.
강철

감사. 그것은 그것을 설명합니다 ... 키 이벤트는 입력 필드에서 작동합니다.
Michael

2

대답

<div 
    className="player"
    onKeyDown={this.onKeyPressed}
    tabIndex={0}
>

나를 위해 작동합니다. tabIndex에는 문자열이 아닌 숫자가 필요하므로 tabIndex = "0"이 작동하지 않습니다.


다른 답변을 수정 하시겠습니까?
Ross Attrill

0

또는 작동 하는 div트릭을 사용 하지만 사용자가 요소가 아닌 뷰에 초점을 맞출 때마다 전체 웹 사이트에 추악한 초점 개요가 표시됩니다. 이는 div가 포커스에서 사용할 CSS를 설정하여 해결할 수 있습니다 .tab_index="0"tabIndex="-1"outline: none

다음은 스타일이 지정된 구성 요소를 사용한 구현입니다.

import styled from "styled-components"

const KeyReceiver = styled.div`
  &:focus {
    outline: none;
  }
`

그리고 App 클래스에서 :

  render() {
    return (      
      <KeyReceiver onKeyDown={this.handleKeyPress} tabIndex={-1}>
          Display stuff...
      </KeyReceiver>
    )

-1

생성자에서 메서드 바인딩이 누락되었습니다. 이것이 React가 제안하는 방법입니다.

class Whatever {
  constructor() {
    super();
    this.onKeyPressed = this.onKeyPressed.bind(this);
  }

  onKeyPressed(e) {
    // your code ...
  }

  render() {
    return (<div onKeyDown={this.onKeyPressed} />);
  }
}

이를 수행하는 다른 방법이 있지만 이것이 런타임에 가장 효율적입니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.