Description
This is following on from a chat in person with @gaearon, and I think is different enough from #66 to warrant its own discussion, so here goes:
I'd like to propose that namespaced attributes generate a simple nested group of attributes
<Comp normal="prop" ns:foo=bar ns:baz=true />
compiles to
createElement(Comp, {
normal: "prop",
ns: {
foo: bar,
baz: true
}
})
This to me is a really natural extension of the existing prop semantics, shouldn't conflict with anything proposed in #65 but it also allows a number of nice design possibilities.
React
// From #66
<Foo react:key="foo" react:ref={callback} prop="hi" />
key
and ref
are now no longer simply "special", they're explicit metadata passed to React. It's a fairly big change to React's core API but I don't see any reason to prevent a codemod doing the bulk of the conversion automatically.
Styled Components
// Styled components use case
const Button = styled.button`
color: ${ sc => sc.primary ? 'white' : 'palevioletred' };
`
<Button type="submit" sc:primary=true />
This is one of the big pain points of designing a library like Styled Components (styled-components/styled-components#439) where we're trying to encapsulate the styling props and the HTML attributes of an element in a single unit. This would make the two types of attributes totally distinct, but without breaking the expressiveness of the component API.
Passthrough props
// Less need for object rest for masking spread properties
const Link = props => {
const { x, y, z } = props
return <a {...props.inner} />
}
<Link x y z inner:href="/" inner:target="_blank" />
This comes up a lot (e.g. Hacker0x01/react-datepicker#517 (comment)) where {...props}
ends up transferring more properties down than is desirable. The above lets the creator of a component explicitly allow "inner" props to be forwarded on.
Alternatively, if a Link
component has a fairly small API and passes on most props, wrapping up all the link-specific props into a single namespace and forwarding on the rest.
// Masking using object rest is slightly simpler too
const Link = ({ link, ...props }) => {
const { x, y, z } = link
return <a {...props}/>
}
<Link link:x link:y link:z href="/" target="_blank" />
I don't propose changing anything else about namespaced props, they should work exactly like non-namespaced ones. It simply gives a component author the ability to partition the API into owned and non-owned properties, in a way that's explicit, named, and simple enough that static type inference/checking should be able to be preserved.
What do you think?