Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React event order

Full reproduction: codesandbox link .

I am trying to create a custom search/select component with react. My problem lies in execution order of events.

When a user focuses in on the text input field, a list with options should be shown. Then when the user clicks on one of the items in the dropdown, the element name should be filled in the text input field and then the list should be hidden.

I achive this by creating a inputFocused boolean state, and rendering list only when inputFocused is true. I attach twop event handlers on the text input itself:

  • onFocus={() => setInputFocused(true)}
    
  • onBlur={() => setInputFocused(false)}
    

But when a user clicks on one of the items, input is not getting filled.

<input
   value={searchTerm}
   onChange={(e) => {
     setSearchTerm(e.target.value);
   }}
   onBlur={() => setInputFocused(false)}
   onFocus={() => setInputFocused(true)}
/>
{inputFocused && (
    <ul>
        <li onClick={() => setSearchTerm(element.name)}>{element.name}</li>
    </ul>
}

Check codesanbox link for better understanding.

I think i understand the problem. onBlur() event triggers before the onClick() event. If i wrap the onBlur callback function inside a setTimout, it will work as expected:

onBlur={() =>
    setTimeout(() => {
        setInputFocused(false);
    }, 100) 
}

I would like to avoid defining a setTimeout.

Is there solution to make sure that onClick() on <li> executes before onBlur() on <input /> ?

like image 581
timtheone Avatar asked Oct 21 '25 04:10

timtheone


1 Answers

You can change onClick to onMouseDown on the list items, and the ordering will be handled properly by the browser.

The events get fired in the order of mousedown -> mouseup -> click (see https://javascript.info/mouse-events-basics#events-order)

like image 136
corypis Avatar answered Oct 23 '25 01:10

corypis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!