facebook/react

React.createComment() would be nice

stevenvachon opened this issue · 15 comments

It'd just have to use document.createComment().

It'd come in handy when working in the Inspector and when compiling to React from other template systems.

The API would be React.createComment(data) if we added this. I took the liberty to update the description of this issue. I don't see why not, other than that it seems a bit unnecessary.

Hmm, if a comment is a DOM element, why would it not be a part of React.DOM?

React.DOM.tagName() is just a set of built-in helpers for calling React.createElement(tagName).

React.createComment(data) is to document.createComment(data)
as
React.createElement(tagName) is to document.createElement(tagName)

Edit: Also note that technically "comment" is not a DOM element. It's a DOM node. (Unless you're talking about document.createElement('comment') which is different.) So if anything React.DOM.comment() would translate into React.createElement('comment').

Ah, yes, agreed.

Would comments be diffed and part of the reconciliation? Are they stripped in production?

Btw you can make a custom Comment component that renders to null in production (but visible in devtools in development). Not sure about the benefits though.

@sebmarkbage Hmm, perhaps a comment can be considered a special case and that's why it makes sense, but I'm not sure it does, a comment node is not universally useful and only really useful for the DOM frontend?

Other than that it should behave like regular ReactElement ... so does it really make sense that it would have its own createComment? Considering all all other elements share the single createElement (DOM, SVG, composite, etc)? createComment makes sense to me if it was universally useful like say "fragment", but it doesn't seem to me like it is and it would be better off just special-cased as createElement('<!-->') or something?

EDIT: I guess it could make sense if we consider that comments could be a helpful debugging tool for any front-end and that it would map to no-op for those that can't make use of it. Hmm...

The browser XML/HTML DOM has 9 interesting kind of nodes in the document:

DOM Class nodeType nodeName
Attr ATTRIBUTE_NODE this.name
Element ELEMENT_NODE this.tagName
Text TEXT_NODE "#text"
CDATASection CDATA_SECTION_NODE "#cdata-section"
DocumentFragment DOCUMENT_FRAGMENT_NODE "#document-fragment"
Comment COMMENT_NODE "#comment"
Document DOCUMENT_NODE "#document"
DocumentType DOCUMENT_TYPE_NODE this.name
ProcessingInstruction PROCESSING_INSTRUCTION_NODE this.target

It's useful to be able to render all of these if you use React to server-side render arbitrary XML documents.

Of these, we already have support for five of them:

DOM Constructor React Constructor React Signature
document.createAttribute() key : value key : value
document.createElement(type) React.createElement(type, props) { type, props }
document.createTextNode(txt) " " string or number
document.createCDATASection(txt) " " string or number
document.createDocumentFragment() [ ] array

We could add support for the final four as well to get complete support:

DOM Constructor React Constructor React Signature
document.createComment(data) React.createComment(data) {type:'#comment',data}
implementation.createDocument() React.createDocument(props) {type:'#document',props}
implementation.createDocumentType (name, publicId, systemId) React.createDocumentType (name, publicId, systemId) {type: '#document-type', name,publicId,systemId}
document. createProcessingInstruction (target, content) React. createProcessingInstruction (target, content) { target, content }

The nodeName of a comment is #comment but it not valid to create it using document.createElement('#comment'). You have to use document.createComment(). That's why I think it should use React.createComment() as the API. It also is a different signature. It accepts only a string "data" field rather than a complete props object.

React.createDocument is useful in combination with React.createDocumentType to create a document type as well as the rest.

React.renderToString(
  React.createDocument({
    children: [
      React.createDocumentType('html', '', ''),
      React.createProcessingInstruction('access-control', 'allow="*.example.com"'),
      React.createComment('Hello this is a secret message for view-source'),
      React.createElement('html', ...)
    ]
  })
)

@sebmarkbage Hmm, I'm a bit confused, I thought the idea was for React.createElement to be the "universal interface" for creating elements which are understood and interpreted by the active frontend (right now, only the DOM). I'm not saying this separation doesn't make sense, but doesn't it mean that DOM frontend implementation details leak into the React API?

Just to illustrate my thoughts, it would make sense to me if it was exposed as ReactDOM.createComment (or w/e), it would then be isolated from the React API and from the other frontends. createDocumentType, createProcessingInstruction, etc doesn't seem like they apply universally to React frontends as they map straight to DOM implementation ... or do we think they apply equally well to other frontends? (i.e. the DOM API is well designed and we're just adopting it)

PS. The React signature for fragment shouldn't be [] should it? I thought being able to key it was important?

@syranide You're right. However, currently the React module is already overloaded with DOM specific APIs such as React.render(ReactElement, DOMNode) and React.findDOMNode(ReactComponent). We'd have to move them all at once to a separate namespace.

It's an interesting exercise though. Would it make sense to have the ability to define a "comment" in other environments too? The others are probably very unique to DOM.

PS. We might need an additional representation for a keyed fragment but there is some discussion going on in that space. Currently it's just [].

@sebmarkbage For the future I guess... :)

If we expand the context a bit, it seems to me it's a matrix of:

  1. Has debugging/logging for human consumption
  2. Has informational data for computer consumption
  3. Has semantic/control meaning for computer consumption

A. Exists in React only (avoids instancing overhead)
B. Exists in React and the front-end renderer
C. Exists in React, the front-end renderer and it's rendered representation (if any)

1A, 1B, 1C makes sense to me at some level, a good developer tool at A/B/C should make it largely pointless, but it seems there's some legitimacy to it still I think.

2A makes no sense to me I think, that's what props are for?
2B, 2C could make sense in some hypothetical scenario where the front-end might be able to gather and present something interesting from the additional data?

3A, 3B is currently used quite a bit I believe (no-op composite components)
3C is abused by quite a few frameworks, it's a good way around the static-ness of HTML DOM, but not something you would ever strive to replicate elsewhere

That's what I could make sense of right now, if it makes any sense... it seems to me there could be some value in comments as a "universal API", however slim it might be.

Anything happening with this?

Not currently.

It seems like the use case for this is very niche, and the effort to make this happen is more than trivial. I’ll close as we’re unlikely to work on this.

It's been 6 years, is there a workaround, or even a chance this could get added now?

Would be nice to be able to insert html comments into the DOM. I ran into wanting to do this. Hope this gets some traction. Thank you!