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" />. 이 시나리오에서는 사용할 수 있습니다 onKeyDownonKeyUp모두 화재 및 올바른 순서.
Tom

12

기능적 구성 요소에서이를 수행하는 또 다른 방법은 다음 useEffectuseFunction같이 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.