React Recap 1: Input Bar Focus
- Published on
As you may have known from my past blog posts, I mainly use Angular. However, I used React and NextJS over a year ago for some of my projects. I told myself that one of these days, I would create a side project just so that I don't forget their important concepts.
A month ago, I started a side project that involves a typing application which in turn will display their accuracy and WPM (words per minute). While testing for possible bugs, I stumbled upon a weird issue.
See below:
In a simple typing application, a user must finish all the words but from what is displayed above, even when the user hasn't finished the words set, the set changes. This took me hours to solve as I didn't know the underlying problem.
Here is the initial code:
{items.map((item, index) => {
return (
<button
key={index}
className=" border-2 rounded-lg p-2 hover:text-gray-500 tracking-wider mr-2 bg-transparent text-white text-center"
onClick={() => {
handleClick(item);
}}>
{item}
</button>
);
})}
This button is used for switching difficulties (Short, Medium, Long). Whenever I switch difficulties, the bug happens. So I investigated the button because there is actually a Reset button right beside it which works similarly. The only difference is that Reset shows a new set of words with a fixed number of words while switching difficulties will show a certain number of words depending on the chosen difficulty.
Reset is coded like this:
<FontAwesomeIcon
className="bg-transparent mr-3"
icon={faArrowsRotate}
style={{ fontSize: 20, color: "white" }}
spin
onClick={() => {
setWords(
generateWords(wordCountInput == null ? undefined : wordCountInput),
);
}}
/>
I tried setting the onClick function for the button earlier to the same onClick content in the Reset button but the issue still persists. This really took me so much of my time!
Since I was already frustrated, in one of my attempts to replicate the bug, after clicking the button for a certain difficulty, I tried clicking a part of the website. The bug did not appear anymore!
I was so confused as to why this was happening. Then I researched for different resources that would not make the focus remain on the button. When you press a button, the focus switches to the button and that is the expected behavior. But because of this, the bug appears. It is also worth noting that my input is not placed in an input element but detected through keystrokes (keyup and keydown) so this also plays a really huge factor. Keystroke detection + focus is on the button = other variables would be affected.
With these being said, this was my fix:
<div className="-ml-10">
{items.map((item, index) => {
return (
<button key={index}
className=" border-2 rounded-lg p-2 hover:text-gray-500 tracking-wider mr-2 bg-transparent text-white text-center"
onClick={(event) => {
handleClick(item);
event.currentTarget.blur();
}}>
{item}
</button>
);
})}
</div>
What event.currentTarget.blur()
does is that it doesn't let the focus stay on the button and won't cause conflicts with the keystrokes that are being detected. It is generally better to ensure that the element with focus is the one that receives the keystrokes, to avoid confusion and unexpected behavior. That's why adding event.currentTarget.blur()
is a good practice in this case, to ensure that the input bar is the element that receives the keystrokes when the user types.
Photo by Alexandru Acea on Unsplash