Surprisingly slow click event in React / Preact

I have the following component (jsfiddle demo here):

export function SomeComponent ()
{
    let t

    console.log("rendering...")

    return <div>
        <input
            type="text"
            defaultValue="value"
            onBlur={() => {
                t = performance.now()
                console.log("blur...")

                const el = document.getElementsByClassName("option")[0]
                var evObj = document.createEvent("Events")
                evObj.initEvent("click", true, false)
                el.dispatchEvent(evObj)
            }}
        />

        <div
            onClick={(e) => console.log("click...", e.isTrusted, performance.now() - t)}
            className="option"
        >Some Option</div>
    </div>
}

If I render it as the only component in an app, i.e.: render(<SomeComponent />, root) and if I then click on the input box and then click on the option box I see the following console output:

rendering...
blur...
click... false 0.5050000036135316
click... true 5.465000052936375  // <-- this is the actual click event

Why does the click, which triggered the blur event, take so much longer to start being handled? And although I am not expecting there is, is there anyway to speed this up?

Tested in: Chrome, Brave, Firefox, Safari.

Preact: 10.5.7 and confirmed in React on jsfiddle

1 thought on “Surprisingly slow click event in React / Preact”

  1. This is not a performance related issue. The click event requires a mousedown followed up a mouseup event. The first mousedown event happens first and triggers the blur event on the input followed, some time later when you release the mouse button, by the mouseup and the click event. The time difference is predominantly how fast you can click the mouse! 🙂

    This code shows the sequence of events:

    function SomeComponent ()
    {
        let t
    
        console.log("rendering...")
    
        return <div>
            <input
                type="text"
                defaultValue="value"
                onBlur={() => {
                    t = performance.now()
                    console.log("blur...")
    
                    const el = document.getElementsByClassName("option")[0]
    
                    var evObj = document.createEvent("Events")
                    evObj.initEvent("mousedown", true, false)
                    el.dispatchEvent(evObj)
    
                    evObj = document.createEvent("Events")
                    evObj.initEvent("mouseup", true, false)
                    el.dispatchEvent(evObj)
    
                    evObj = document.createEvent("Events")
                    evObj.initEvent("click", true, false)
                    el.dispatchEvent(evObj)
                }}
            />
    
            <div
                onMouseDown={(e) => console.log("mouse down...", e.isTrusted, performance.now() - t)}
                onMouseUp={(e) => console.log("mouse up...", e.isTrusted, performance.now() - t)}
                onClick={(e) => console.log("click...", e.isTrusted, performance.now() - t)}
                className="option"
            >Some Option</div>
        </div>
    }
    
    
    ReactDOM.render(
    <SomeComponent />,
    document.getElementById('container')
    );
    

    Which gives the output:

    "mouse down...", true, NaN
    "blur..."
    "mouse down...", false, 1.459999941289425
    "mouse up...", false, 2.7149999514222145
    "click...", false, 10.524999932385981
    "mouse up...", true, 12.214999995194376
    "click...", true, 12.69000000320375
    
    Reply

Leave a Comment