React'te Esc Tuşuna Nasıl Basılacağı ve Nasıl Kullanılacağı


126

Reactjs'de Esc tuşuna basmayı nasıl tespit ederim? Jquery'ye benzer şey

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

Algılandıktan sonra bilgileri bileşenlere aktarmak istiyorum. Son aktif bileşenin çıkış tuşuna basılmasına tepki vermesi gereken 3 bileşenim var.

Bir bileşen aktif hale geldiğinde bir tür kayıt yapmayı düşünüyordum

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>
    )
  }
}

ve tüm bileşenlerde

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)}/>
    )
  }
}

Bunun işe yarayacağına inanıyorum ama daha çok bir geri arama gibi olacağını düşünüyorum. Bunu halletmenin daha iyi bir yolu var mı?


Bu şekilde yapmak yerine aktif bileşenin hangisi olduğunu saklayacak bir akı uygulamanız yok mu?
Ben Hare

@BenHare: Hala oldukça yeniyim. React'e geçmenin fizibilitesini araştırıyorum. Akıyı denemedim, bu yüzden çözüm için akıma bakmamı öneriyorsunuz. Not: ESC tuş basımını algılamaya ne dersiniz?
Neo

5
Sadece açıklığa kavuşturmak için, ilk kod bloğu gibi belge düzeyinde tuşa basma algılamasını mı arıyorsunuz? Yoksa bu bir giriş alanı için mi? İkisini de yapabilirsiniz, sadece bir cevabı nasıl çerçeveleyeceğimi bilmiyorum. İşte hızlı bir belge düzeyi örneği: codepen.io/anon/pen/ZOzaPW
Brad Colthurst

Belge seviyesi iyi olurdu :)
Neo

Yanıtlar:


229

Belge düzeyinde bir anahtar olay işleme arıyorsanız, bunu sırasında bağlama componentDidMounten iyi yoldur ( Brad Colthurst'un codepen örneğinde gösterildiği gibi ):

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/>
    )
  }
}

Olası hataları ve bellek sızıntılarını önlemek için, unmount sırasında anahtar olay dinleyicisini kaldırdığınızdan emin olmanız gerektiğini unutmayın.

DÜZENLEME: Kanca kullanıyorsanız, useEffectbenzer bir etki yaratmak için bu yapıyı kullanabilirsiniz :

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
Üçüncü argüman nedir addEventListenerve removeEventListener?
jhuang


2
@jhuang , genellikle benzemeyenfocus olayların yakalanıp yakalanmayacağını belirten useCapture argümanıdır . İlgili değildir keydown, ancak isteğe bağlı olmadığı için genellikle IE <9 ile uyumluluk için belirtilir.
Chase Sandmann

Ben sarmak zorunda this.escFunctiongibi bir fonksiyonu haline function() { this.escFunction(event) }aksi takdirde herhangi bir "keydown" olmadan Sayfanın yüklendiği yürütme edildi.
M3RS

2
3. argüman olarak 'yanlış'ı eklemeye gerek yoktur. Varsayılan olarak yanlıştır.
NattyC

25

React'ten escape'larıkeyCode (27) dinlemek isteyeceksiniz :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'un Sorunun yorumlarında yayınlanan CodePen'i , diğer anahtarlar için anahtar kodlar bulmak için yararlıdır.


15
Onun 'için değer göründüğünden tepki belirtti düşünüyorum değil ateş onKeyPressbasılmasını anahtar ESC ve odak içinde olduğu zaman olay <input type="text" />. Bu senaryoda, kullanabilir onKeyDownve onKeyUpher ikisi de yangını ve doğru sırayla.
Tom

12

Bir fonksiyonel bileşenin Bunu yapmak için başka bir yol, kullanmaktır useEffectve useFunctionbu gibi:

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 yerine, bir useStateşeyi tetiklemek için kullanabilirsiniz .


7

Kullanımları tepki SyntheticKeyboardEvent yerel tarayıcı olayı sarmak için ve bu Sentetik olay sağlar anahtar özelliği adında ,
böyle kullanabilirsiniz:

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
eğlenceli Gerçek şu ki, aşağıda IE9 ve / veya Firefox 36 veya desteklemek gerekirse e.keyiçin Escapegeri geliyor Esc#triggered
aug

4

Yeniden kullanılabilir bir React kanca çözümü için

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

Kullanımı:

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

3
Çözüm, onEscape işlevinin değiştirilmesine izin vermiyor. UseEffect için dep dizisi olarakMemo kullanmalı ve onEscape'i aktarmalısınız
Neo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.