-
Notifications
You must be signed in to change notification settings - Fork 47.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for JSX tag namespaces <React:DOM:div /> #760
Conversation
cc @vjeux |
return name; | ||
} else { | ||
return quoteNamespacedTagName(namespace, true) + | ||
(isValidJSIdentifier(name) ? '.' + name : "['" + name + "']"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'[' + JSON.stringify(name) + ']'
would make me feel a bit better. hyphens seem a bit weird to support though.
@spicyj Ah yes, that was copied from the existing As for hyphens, tag names and attributes share the same |
return name; | ||
} else { | ||
var append = isValidJSIdentifier(name) ? | ||
'.' + name : '[' + JSON.stringify(name) + ']'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: put the else
part in the next line to make it easier to read
var append = isValidJSIdentifier(name) ?
'.' + name :
'[' + JSON.stringify(name) + ']';
@vjeux Thanks! All nits should have been resolved except for the error, that convention is used for other errors (in those files at least), so I'll hold off on that for moment unless you want me to correct all of them. |
} | ||
|
||
return identifier.name; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: you don't need the else since you return from the if branch :) This lets you have one less level of indentation
@vjeux All fixed, however note that you must apply the |
This looks very promising! |
This would be a very cool feature to have added (I'm experiencing exactly this problem at the moment). |
I also very much want to be able to do this. Makes me sadder than a reddit user without cat pics not to have it. |
A reason not to use |
We've been having the same problem for a while. We use require.js and without this PR fix we have a few choices: a) Have really unreadable code, when using multiple components, i.e. not use JSX syntax and write it in vanilla js Right now we're using a mix of a),c) and d) depending on how much nestling we have of multiple components. So big upvote on this PR request! |
@jenso: Why not doing b) and having a component per file? We do that internally and it's worked very well for us. |
Though I agree that one component per file is probably better, I don't think it's React's job to force a particular way of organizing files. |
Namespacing would be a very useful tool and I believe those who have expressed desire for it on this thread would benefit from some form of namespacing, but I'm not sure this is the best way to deal with that need in a general sense. Specifically, I am opposed to this particular approach because it conflates "namespacing" with code organization. If the only way to namespace your components is to put them together in a module (or nest them together within an object), then namespacing of components can quickly become at odds with the way one organizes their code -- which is a pretty unfortunate trade-off to have to make. Consider, for example, if someone wanted to create a "common component library" (let's call it CCL for short) where it is desired that all of the components should be namspaced with "CCL". So The only way the library author would be able to achieve this are:
ccl.js
Obviously for a large library, this is pretty unacceptable as it doesn't allow the library author to break their code into smaller more manageable (testable/isolated) pieces. It might be reasonable for smaller libraries and codebases, but it's not a scalable way to write a component library.
checkbox.js
textinput.js
ccl.js
This is MUCH more reasonable from the library author's perspective, but it pushes some issues off to the users of the library. The users can now choose how they will consume the lib, but their choice comes with trade-offs: a) Users can import only the components they want to use in their local file, but forgo namespacing to do so: thing-that-uses-ccl.js
b) Users can import from an aggregator module -- which includes all of the components in the namespace -- to achieve namespacing in their local file: thing-that-uses-ccl.js
This second solution is still pretty unfortunate for a few reasons:
Another note: I would like to defer the |
In summary at a higher level: If we went with this means of namespacing, it would mean namespacing is really only a feature usable by smaller teams and/or codebases. I'd really like to see us try to come up with a more scalable solution so that everyone can benefit and use them. |
@jeffmo Valid concerns, but intuitively to me it seems that by those restrictions, the only valid solution is no "namespacing". I don't see what middle-ground there is between a component, and components in an object. It also seems weird to me that this would be considered an issue when React's own DOM components are exported as But I truthfully respect your opinion on this, I'm not really an architecture guy, but more of a get shit done and solve it later (and then later), and it's certainly not always the right "attitude". However, I would like to put another perspective on it by saying that I think it's easier to get people to start using React if they can continue with their bad habbits and then you show them light. Rather than have React feel alien simply because it doesn't work/support the way they are used to and feels encumbering instead. JavaScript micro libraries popping up everywhere is not just because, but because people been taught that it's better (for the worse). I would rather have 1 person using React the right way and 1 person using it the wrong way, than just 1 person using it the right way. Put up a big guide on best practices in the docs, the people who want to learn will read it and happily submit, those who don't simply aren't ready and forcing them will only push them away (that said, one should pick the right solution, but lets not artificially limit users for philosophical reasons). Right now we kind of have neither. |
For what it's worth, including only some of the tags from React.DOM wouldn't give an appreciable size savings. |
@jeffmo PS. To me |
What if namespacing a component didn't mean "nested in an object", but instead it meant "this component claims to be a member of this namespace"? I'm totally riffing here -- and I don't claim these ideas are well thought-out -- but just as a thought experiment: checkbox.jsx
thing-that-uses-MyLibrary.jsx
(which desugars to) thing-that-uses-MyLibrary.desugared.js
I think this would address the issue of "true namespacing" where the components dictate what namespace they belong to (not the location of the code), and it would mean that namespacing could probably still be enforced statically with some tooling and a module system that supports statically-analyzable imports/exports. It would not necessarily make life easier for those who use nested objects as a means of namespacing -- though I would imagine we could make some simple tweaks and utilities to make that not horribly complicated: MyLibrary.not-a-module.js
ReactUtils.js
|
The namespace could be verified at runtime (or even statically without types if you have the right setup -- a statically analyzable module system + tooling that supports it + string literals for the namespace entry in the It also serves as documentation for the reader of the code. And it leaves the door open to any module system rather than just a particular style Thoughts here? |
It would also not solve the issue of having to extract items from a nested object into a local binding:
But this is necessary in just about any module system anyway (you have to put That said, as I mentioned to @spicyj on IRC, if we want to talk about opening up JSX to accept more than just an I think if we do that though, we should have a "more endorsed" means of namespacing first so that it's clear that we discourage the use of object-nesting for namespacing purposes. People could still do |
Yea, I used I have no problem with supporting a default namespace + runtime disambiguation though |
@zpao What about |
If adding support for |
Supporting arbitrary JS expression may be tricky. What happens if you write
Are the two expressions executed? What if they don't match? Lots of corner cases |
@syranide, let's make it so it's only possible to have dot format. Forget I said anything about |
@zpao Sorry for the delay, been out sick for a bit. I'll polish up the PR to use |
@jeffmo Hmm, do you want this implemented "properly" as namespaces (the way it's currently implemented), or should I basically extend the valid symbols with |
IIRC I think we agreed to go with non-computed member expressions -- so no more colon.
|
@jeffmo Right, but how do you want it implemented? It's currently implemented as a nested structure called So the question is, should we just use the same nested structure still, |
Ah -- In this case we should update the parser to parse either Identifier or MemberExpression |
@jeffmo Updated according to our discussions (you basically coded it, haha). Just shout if there's anything you want changed. It depends on facebookarchive/esprima#7 to function, but it should not break without it. @zpao As per the nudge :) |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
@jeffmo Just reminding in-case you forgot about this PR since the esprima PR landed a while ago (facebookarchive/esprima#7). When done you can also tick |
Support for JSX tag namespaces <React:DOM:div />
welp. |
Nice work 👍 |
woot woot! thanks guys! |
Thank you :) 🍰 |
👍 |
👍 |
This has been suggested and discussed before: #74, #221, facebookarchive/esprima#6, etc.
But it seems to me like the discussions rather died out than a rejection of the issue. So here's for one final resurrection of the issue, with a proper implementation, using the XML-namespaces as seemed to be preferred by @jeffmo.
In my opinion, this issue points to a very pleasant but not required feature that vanilla JS has, that JSX currently lacks. To me, it also highlights a possible issue with respect to best practices for sharing components and frameworks, as this may have impact design decisions depending on the authors preference for JS or JSX. Having to locally require and assign every single component intended to be used is tedious and unnecessarily verbose. Simply being able to refer to a collection of components, as we easily can in JS, should be available to JSX as well.
This brings JS and JSX to parity on this issue in my opinion, without inventing custom features or weird syntaxes, and it seems to me that this should not block any important future design decisions (that would be compatible with JSX), and it's entirely optional for the user.
Technically, the JSX implementation quotes invalid JS identifiers resulting from unusual characters in namespaces or tags (when possible), which explains the implementation of
quoteNamespacedTagName
.This PR depends on facebookarchive/esprima#7 for
fb-esprima
, which is why the tests are failing.All feedback and criticisms are appreciated.
Fixes #74.