React에서 Esc Key Press를 감지하는 방법 및 처리 방법


124

reactjs에서 Esc 키 누르기를 어떻게 감지합니까? jquery와 비슷한 것

$(document).keyup(function(e) {
     if (e.keyCode == 27) { // escape key maps to keycode `27`
        // <DO YOUR WORK HERE>
    }
});

일단 감지되면 구성 요소에 정보를 전달하고 싶습니다. 마지막 활성 구성 요소가 이스케이프 키 누름에 반응해야하는 세 가지 구성 요소가 있습니다.

구성 요소가 활성화되면 일종의 등록을 생각했습니다.

class Layout extends React.Component {
  onActive(escFunction){
    this.escFunction = escFunction;
  }
  onEscPress(){
   if(_.isFunction(this.escFunction)){
      this.escFunction()
   }
  }
  render(){
    return (
      <div class="root">
        <ActionPanel onActive={this.onActive.bind(this)}/>
        <DataPanel onActive={this.onActive.bind(this)}/>
        <ResultPanel onActive={this.onActive.bind(this)}/>
      </div>
    )
  }
}

그리고 모든 구성 요소에

class ActionPanel extends React.Component {
  escFunction(){
   //Do whatever when esc is pressed
  }
  onActive(){
    this.props.onActive(this.escFunction.bind(this));
  }
  render(){
    return (   
      <input onKeyDown={this.onActive.bind(this)}/>
    )
  }
}

나는 이것이 효과가 있다고 믿지만 콜백과 더 비슷할 것이라고 생각합니다. 이것을 처리하는 더 좋은 방법이 있습니까?


이런 식으로 수행하는 대신 활성 구성 요소를 저장할 플럭스 구현이 없습니까?
— Ben Hare

@BenHare : 나는 아직도 그것에 꽤 새로운. React 로의 마이그레이션 가능성을 조사하고 있습니다. 나는 플럭스를 시도하지 않았으므로 솔루션을 위해 플럭스를 조사해야한다고 제안하고 있습니다. 추신 : ESC 키 누르기를 감지하는 것은 어떻습니까?
— 네오

5
명확히하기 위해 첫 번째 코드 블록과 같이 문서 수준에서 키 누름 감지를 찾고 있습니까? 아니면 입력 필드입니까? 당신은 둘 중 하나를 할 수 있습니다. 나는 대답을 구성하는 방법을 잘 모르겠습니다. 다음은 빠른 문서 수준입니다. codepen.io/anon/pen/ZOzaPW
— Brad Colthurst 2016 년

문서 수준은 괜찮을 것입니다. :)
— Neo

답변:


229

문서 수준의 키 이벤트 처리를 찾고 있다면 그 동안 바인딩하는 componentDidMount것이 가장 좋은 방법입니다 ( Brad Colthurst의 코드 펜 예제에서 볼 수 있음 ).

class ActionPanel extends React.Component {
  constructor(props){
    super(props);
    this.escFunction = this.escFunction.bind(this);
  }
  escFunction(event){
    if(event.keyCode === 27) {
      //Do whatever when esc is pressed
    }
  }
  componentDidMount(){
    document.addEventListener("keydown", this.escFunction, false);
  }
  componentWillUnmount(){
    document.removeEventListener("keydown", this.escFunction, false);
  }
  render(){
    return (   
      <input/>
    )
  }
}

잠재적 인 오류 및 메모리 누수를 방지하려면 마운트 해제시 키 이벤트 리스너를 제거해야합니다.

편집 : 후크를 사용하는 경우이 useEffect구조를 사용하여 유사한 효과를 생성 할 수 있습니다 .

const ActionPanel = (props) => {
  const escFunction = useCallback((event) => {
    if(event.keyCode === 27) {
      //Do whatever when esc is pressed
    }
  }, []);

  useEffect(() => {
    document.addEventListener("keydown", escFunction, false);

    return () => {
      document.removeEventListener("keydown", escFunction, false);
    };
  }, []);

  return (   
    <input />
  )
};

7
addEventListener및 의 세 번째 인수는 무엇입니까 removeEventListener?
— jhuang


2
@jhuang 일반적으로focus . 와 같이 버블 링되지 않는 이벤트를 캡처할지 여부를 지정하는 useCapture 인수입니다 . 와 관련이 keydown없지만 이전에는 선택 사항이 아니 었 으므로 일반적으로 IE <9와의 호환성을 위해 지정됩니다.
— Chase Sandmann

나는 this.escFunction같은 함수 로 래핑해야했다 function() { this.escFunction(event) }. 그렇지 않으면 페이지로드시 "키 다운"없이 실행되고 있었다.
— M3RS

2
세 번째 인수로 'false'를 포함 할 필요가 없습니다. 기본적으로 거짓입니다.
— NattyC

25

ReactkeyCode 에서 escape (27) 를 듣고 싶을 것입니다 .SyntheticKeyBoardEvent onKeyDown

const EscapeListen = React.createClass({
  handleKeyDown: function(e) {
    if (e.keyCode === 27) {
      console.log('You pressed the escape key!')
    }
  },

  render: function() {
    return (
      <input type='text'
             onKeyDown={this.handleKeyDown} />
    )
  }
})

질문의 댓글에 게시 된 Brad Colthurst의 CodePen 은 다른 키의 키 코드를 찾는 데 도움이됩니다.


15
나는 그것의 가치가 나타납니다 반작용이 추가 생각 하지 화재 onKeyPress누르는 키가 ESC하고 초점 안에있을 때 이벤트를 <input type="text" />. 이 시나리오에서는 사용할 수 있습니다 onKeyDown및 onKeyUp모두 화재 및 올바른 순서.
— Tom

12

기능적 구성 요소에서이를 수행하는 또 다른 방법은 다음 useEffect과 useFunction같이 and 를 사용하는 것입니다.

import React, { useEffect } from 'react';

const App = () => {


  useEffect(() => {
    const handleEsc = (event) => {
       if (event.keyCode === 27) {
        console.log('Close')
      }
    };
    window.addEventListener('keydown', handleEsc);

    return () => {
      window.removeEventListener('keydown', handleEsc);
    };
  }, []);

  return(<p>Press ESC to console log "Close"</p>);
}

console.log 대신 useState무언가를 트리거 하는 데 사용할 수 있습니다 .


7

용도는 반응 SyntheticKeyboardEvent 기본 브라우저 이벤트를 래핑이 합성 이벤트가 제공 키 속성의 이름 ,
당신은 다음과 같이 사용할 수 있습니다 :

handleOnKeyDown = (e) => {
  if (['Enter', 'ArrowRight', 'Tab'].includes(e.key)) {
    // select item
    e.preventDefault();
  } else if (e.key === 'ArrowUp') {
    // go to top item
    e.preventDefault();
  } else if (e.key === 'ArrowDown') {
    // go to bottom item
    e.preventDefault();
  } else if (e.key === 'Escape') {
    // escape
    e.preventDefault();
  }
};

3
재미있는 사실은 당신이 아래 IE9 및 / 또는 파이어 폭스 36을 지원해야하는 경우 e.key를 위해 Escape로 돌아 오면 Esc#triggered
— 8월

4

재사용 가능한 React 후크 솔루션

import React, { useEffect } from 'react';

const useEscape = (onEscape) => {
    useEffect(() => {
        const handleEsc = (event) => {
            if (event.keyCode === 27) 
                onEscape();
        };
        window.addEventListener('keydown', handleEsc);

        return () => {
            window.removeEventListener('keydown', handleEsc);
        };
    }, []);
}

export default useEscape

용법:

const [isOpen, setIsOpen] = useState(false);
useEscape(() => setIsOpen(false))

3
이 솔루션은 onEscape 기능의 변경을 허용하지 않습니다. useMemo를 사용하고 useEffect의 dep 배열로 onEscape를 전달해야합니다
— Neo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.