This week I had an issue with a react component that took a little time to debug. There did not seem to be any good explanations as to what was happening, so I thought I’d write it up in case someone is googling to find a solution.
Component and desired behavior:
The component was created to provide custom controls on a video using the <video> element provided by html5. Within the react application there is a reference created to the video element which is passed in via a context provider.
The desired behavior is to have both mouse click actions, including: play, pause, forward, rewind. It was also desired to have keyboard commands, include allowing the space bar to play/pause and forward/back arrows to forward/rewind.
The observed bug:
- If you pressed the space bar to play / pause, everything worked.
- If you clicked on the play / pause icons, everything worked.
- If you pressed the space bar to play, then clicked the pause button, everything worked.
- If you clicked the play button, then pressed the space bar, it did not work.
Essentially anytime you tried to go from the click event to the keyup event, the behavior did not work as expected.
After some reading up on the react docs: React Synthetic Events and gaining some insight on how the events were bubbling up within the application , I placed some console.log statements to get an understanding what was occurring.
What I noticed was that when you pressed the space bar then clicked the play or pause icon, I’d see: “playing via spacebar” followed immediately by “pausing via mouse click”.
What now seems fairly clear, here is what happened:
- clicking the icon moved the focus to that element
- pressing the spacebar triggered the appropriate play/pause command
- However, because the focus was still on the icon the spacebar was also triggering the onClick event.
Prior to figuring this out, I had tried several attempts at using stopPropogation() or stopImmediatePropogation(), although after seeing the results of the console logging, I realized I just needed to stop behavior of the spacebar causing the onClick to fire.
A couple preventDefault() statements and everything is now working as intended.
Here is the working solution: