mitosis
mitosis copied to clipboard
How will you handle scenarios where JSX is lossy?
Like for example, a differentiation between attributes and arguments?
In jsx, there is only the 'prop', which react uses for both html attributes and component arguments
Well so the benefit of JSX lite is it is more restrictive than plain JSX, we enforce this at the compiler level as well as have an eslint plugin to give guidance in the IDE. So we can be more strict than plain react, e.g.
<div foo="bar" ... /> <- is all dom attributes
<Thing foo="bar" ... /> <- is all component arguments
<Thing foo="bar" ... /> <- is all component arguments
but I mean, what if the component needs to know the difference between component arguments and attributes? can jsx-like differentiate? like:
map <Thing @foo=1 foo=1 /> to, in, Thing: props.args: { foo: 1 }, props.attributes: { foo: '1' }
So that is the components choice. JSX Lite does not assume you want any props to be attributes, you choose what should be. A common pattern in React land for this to do things like
function MyComponent(props) {
const { arg1, arg2, ...attributes } = props;
return <div {...attributes} />
}
So in your example above, every prop is treated as @foo. We don't have any assumption that each component maps to a tag of any kind. They are all just arguments the component can handle as they desire, except of course for plain html tags then in only that case all props are just attributes.
Yeah, I've used React for a long time. 👍
I take issue with the
const { arg1, arg2, ...attributes } = props;
pattern though, because if any extra args are accidentally passed, they are treated thrown an to the div.
Sure, you can say "don't pass extra stuff", but with how much spreading of props, it's really easy for folks to make mistakes and throw extra args / attributes all over the place.
I would just like some syntax in react to make the differentiation between attributes and args explicit to help mitigate this issue. It'd be possible with a build-time transform, but I haven't seen one made, afaict
Yeah so your point above is why imo I never actually use that pattern either, and always opt to only supporting explicit args to components. We have planned to allow custom syntax extensions via plugins (that hook into babel) to allow defining your own rules/syntaxes such as this as an optional addon, so I can keep this use case in mind
Also, I'm curious, is there any frameworks you have used that do the above well that you think is a good pattern to emulate?
Also, I'm curious, is there any frameworks you have used that do the above well that you think is a good pattern to emulate?
atm, I use Ember, which splits args and attributes. It's really nice, because all attributes are known and separate from args -- so there is a special named spread that can go on elements:
<SomeComponent
class='foo'
data-test="something"
@argFoo="The text"
/>
<!-- inside <SomeComponent /> -->
<button type="button" class="merged with attributes" ...attributes>
{{@argFoo}}
</button>
<!-- which then results in the output HTML (ignoring line breaks) -->
<button
type="button"
class="merged with attributes foo"
data-test="something"
>
The text
</button>
No need to filter out attributes like with props. Last I was doing React, I had a helper function which knew of all possible attributes.. which was kinda buggy because different elements take different attributes.
Ah yes I see. so at the moment JSX lite will enforce that in your example, all key/value pairs will be treated as @arg, so for example
<Foo bar="baz" two="three" />
would map to
<Foo @bar="baz" @two="three" />
our goal is not necessarily to support all features of all frameworks, but to lean on standard primitives that work across (aka a core subset of features), and I personally when working with react, vue, etc that don't have such a divide haven't found it to be a problematic scenario, and you can always wrap components with your own divs or the component shave options using spread operators to allow forwarding attributes if they choose too
Albeit I do see value in this, so I'm open to reconsidering this if this use case becomes more common and in demand by the community though
but to lean on standard primitives
wouldn't the primitive be the more specific thing, like in your example where everything is prefixed with @ and transpiled away for React, for example?
shave options using spread operators to allow forwarding attributes if they choose too
this is my point, you're having to work around limitations of an imprecise syntax
Just linking to the RFC since that is likely where any resolution would happen and not until React 18 or so. https://github.com/facebook/react/issues/11347