question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature Request: Event Modifiers support

See original GitHub issue

I’m moving from Vue to React recently, and one of the few practical features I miss is native Event Modifiers support.

Vue supports several types of native events that make development very convenient. The ones I miss the most are:

  • .stop: same as e.stopPropagation().
  • .prevent: same as e.preventDefault();

Pros:

  • Allows the function defined in the handle to perform its main function without worrying about the event flow;
  • Facilitates the reuse of callbacks that control the flow differently, but achieve the same result;
function handleClick(e) {
    console.log('ok');
}

function handleClickWithStop(e) {
    e.stopPropagation();
    handleClick(e);
}
<div onClick={handleClickWithStop}>must stop</div>
<div onClick={handleClick}>must continue</div>

Becomes:

function handleClick(e) {
    console.log('ok');
}
<div onClick.stop={handleClick}>must stop</div>
<div onClick={handleClick}>must continue</div>

Cons:

The only thing I can think of being “against” is that it might increase the cost of converting from JSX to native JS. Although I think this only happens during the build process. Right?

During the conversion process, events will need to identify the .indexOf('.') and then apply the necessary wrappers:

React.createElement(
    'div',
    { onClick: function (e) {
          e.stopPropagation();
          handleClick(e);
      } }
)

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:4
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
markeriksoncommented, Sep 10, 2022

Yeah, strictly speaking the JSX transform isn’t part of “React” the software library at all. JSX was invented for use with React, but many tools now implement that syntax (even Vue!), and the output is just the function calls to React.createElement() or the equivalent for other libraries.

If you want to get a sense of some other proposed changes to the JSX spec (none of which have become reality), see the discussions in this thread:

0reactions
rentalhostcommented, Sep 11, 2022

@gaearon your question is very interesting. I’ll answer based on what vue does in this case:

When an element has only one @click="handleClick", for example, we get something like:

_createElementVNode("div", {
    onClick: _cache[0] || (_cache[0] = (...args)=>(_ctx.handleClick && _ctx.handleClick(...args)))
})

However, if we have a definition @click and @click.stop at the same time, we will have:

_createElementVNode("div", {
    onClick: [
        _cache[0] || (_cache[0] = (...args)=>(_ctx.handleClick && _ctx.handleClick(...args))), 
        _cache[1] || (_cache[1] = _withModifiers((...args)=>(_ctx.handleClick && _ctx.handleClick(...args)), ["stop"]))
    ]
})

Which indicates that vue accepts this condition well, transforming .onClick into an array of events, instead of a direct event (like the first case).

Not only that, but @click (and events in general) allows the use of an array containing multiple definitions for methods, so the same event can perform different functions without a wrapper: @click="[ handleClick($event), handleClickTwo($event) ]"

_createElementVNode("div", {
    onClick: _cache[0] || (_cache[0] = $event=>([$setup.handleClick($event), $setup.handleClickTwo($event)]))
})

As for the example of ...props, the code @click="handleClick" v-bind:onClick="handleClickTwo" is converted to:

_createElementVNode("div", {
    onClick: [$setup.handleClick, $setup.handleClickTwo]
}, "teste")

As for third-party code, you can even define both @click and @click.stop with independent supports, but at this point it would be overkill. If the code user needs a stop beyond what is developed by the third party code, then he will have to do it directly by the JS.

In vue, events are declared explicitly using @. Which means that @something is necessarily an event, and stop and prevent support are applicable exclusively in these cases. In addition, there is other support for specific events such as @keydown.enter, @keydown.space etc. I don’t think anything at this level can be done in React.

Read more comments on GitHub >

github_iconTop Results From Across the Web

allow `once` modifier on custom event handlers · Issue #2654 ...
Having the ability to add modifiers for DOM events (#1088 )is really great, for example: on:click|once={handleClick}.
Read more >
Modifier support needed for "Scroll by" action
I want to map alt+mouse wheel to a two finger Magic Mouse swipe. Unfortunately, I cannot do this because the "scroll by" action...
Read more >
Feature request: Translucent modifiers - Prusa Forum
I was just thinking about this last night when I tried to place a support enforcer and couldn't really see how it overlapped...
Read more >
Feature Request: Add Modifiers or Options to Services
Creating a separate service for each wanted modifier does not work, because just like items, certain modifiers only apply to certain services.
Read more >
Language Server Protocol Specification - 3.17
The base protocol offers support for request cancellation. ... Not every language server can support all features defined by the protocol.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found