Dusttt
Dusttt

Reputation: 29

ReactJS Hook useState with Key press event

I'm building a piano that display some css style when user "press" some keyboard button (keydown) ( click multiples different button at the same time also allow). When user stop pressing (keyup) , simply remove those css style .

Ex: click and hold "A", "B", "C" will add active class to them , release "C" only remove active class to "C".

I plan to do it with react hook like this :

  const [press, setPress] = useState([]); //Hook state
  
  // store the keyboard user click into an array
  const keyDown = (e) => {
    if (e.repeat) {
      return;
    }
    setPress((oldArr) => [...oldArr, e.key]);
  };
  
  // remove only the one that user release 
  const keyUp = (e) => {
    const keyRemove = press.filter((key) => key !== e.key);
    setPress(keyRemove);
  };

// add key press event listener
  useEffect(() => {
    window.addEventListener("keydown", keyDown);
    window.addEventListener("keyup", keyUp);
    return function cleanup() {
      window.removeEventListener("keydown", keyDown);
      window.removeEventListener("keyup", keyUp);
    };
  }, []);
  
  //just pass the press arr to child element
    return (
    <div className="main">
        <Child press={press} /> 
    </div>
  );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

The keydown event work's fine , but the keyup keep reset the press array back to empty . I don't understand why this work like this . Can someone explain it for me ? Thank in advance

Upvotes: 0

Views: 1425

Answers (2)

VeeGee
VeeGee

Reputation: 52

changing the key up filter works for me

const keyRemove = press.filter(function(value, index, arr){ 
        return value !== e.key;
});

Upvotes: 0

Viet
Viet

Reputation: 12787

I think the problem is your logic in keyUp. You need to update the filter:

const keyUp = (e) => {
  setPress(press.filter((key) => key !== e.key));
};

Upvotes: 2

Related Questions