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: Directives for components

See original GitHub issue

Currently, the code <Counter use:example="Hello World" /> compiles into

createComponent(Counter, {
  "use:example": "Hello World"
})

We could probably make it work into

createComponent(Counter, {
  ref(node) {
    example(node, 'Hello World');
  },
});

since ref is already a special prop for both host and components.

What do you think?

The only design challenge would be that props.ref can be assigned anytime, anywhere which makes it lack constraint unlike host nodes, posing some memory leaks.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
edemainecommented, Jul 10, 2022

First, whatever we decide here in general, even if it’s “do nothing”, I think we should modify <Dynamic> to support directives when it component is a string so an Element gets created. Otherwise, every library that uses <Dynamic> in this way (e.g. styled components, MDX, …) would need to do this themselves, which seems like gross repetition.

Now, reflecting on this issue more, I’m now much more inclined to go with @LXSMNSYC’s original suggestion (instead of modifying spread):

use:foo={bar} is always just syntactic sugar for ref={(r) => foo(r, bar)} (plus automatic merging of such refs)

I think this is nicely consistent, and easy to teach and understand. The current docs say (and have said for a long time) “In a sense this [use:___] is just syntax sugar over ref but allows us to easily attach multiple directives to a single element.”

The arguments against this are that “ref could get passed anything! and at any time!” But this is a general issue with ref, and in practice props.ref is often just passed on to a relevant DOM element. We still find ref useful in many situations with components. I think we will find use:foo to also be useful in many situations with components, whereas the current behavior is basically never useful, because with it the component needs to know about directives.

With this proposal, the user of a directive (whoever writes <Comp use:foo/>) needs to know how <Comp ref={ref}> will set ref, and what foo will do with that as an argument. This seems consistent with how directives work for Elements now. I don’t expect to be able to call function foo with any argument, only those that it’s designed to work for. If I know Comp will give me such a thing via ref, then I can use use:foo. Currently one has to write ref={foo} or ref={(r) => foo(r, bar)}, which gets especially messy with multiple refs. The whole point of use: is to provide this syntactic sugar.

On the TypeScript side, one issue is that interface DirectiveFunctions would need to change, so that the first argument is unknown instead of Element. But the whole point of DirectiveFunctions is for the user to override it to specify the correct types for the directive, so this makes sense.

https://github.com/ryansolid/dom-expressions/blob/df0486922723a20a2b346d08af3c5ce1367489ed/packages/dom-expressions/src/jsx.d.ts#L63-L65

Hopefully we can extend DirectiveFunctionAttributes<T> to properly detect a component with props.ref types, and use the argument type there to specify what the directive will be given as first argument.

1reaction
edemainecommented, May 18, 2022

I had the following behavior in mind:

  1. If props.as is a native element, it would work like a regular directive.
  2. If props.as is a component, use:myDirective (=true?) would get passed in as a prop. The component could then do what it wants with the directive, including passing it down via spread to a native element or other component.

This is very close to the current behavior, which just does case 2 in all cases. I’m proposing changing the behavior when you get a native element.

I’m not exactly sure how ergonomic the DX would be here, but this change to spread would at least “fix” Dynamic when component is a native element, which seems like a nice step.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Feature Request] Add longpress directives to Vuetify ... - GitHub
Problem to solve A common way to modify data is to add a button which calls a function to perform some logic.
Read more >
Attribute directives - Angular
Change the appearance or behavior of DOM elements and Angular components with attribute directives. See the live example / download example for a...
Read more >
Developer Guide: Directives - AngularJS: API
At a high level, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell...
Read more >
Introducing the Directive Composition API in Angular v15
We are pleased to announce the new Directive Composition API, a long-awaited feature that allows Angular Developers to reuse behaviors from ...
Read more >
Angular 15: What's New in the Latest Version of Angular v15?
This feature was inspired by the most popular feature request on GitHub, asking to apply directives to a host element. @Component({
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