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

PROPOSAL: Allow void elements to have children with override property #12396

Closed
dxprog opened this Issue Mar 18, 2018 · 2 comments

Comments

Projects
None yet
2 participants
@dxprog

dxprog commented Mar 18, 2018

Do you want to request a feature or report a bug?

Feature.

What is the current behavior?

When creating one of the whitelisted void elements, an error is thrown:

<link>https://reactjs.org/blog/</link>
<link dangerouslySetInnerHTML={{ __html: 'https://reactjs.org/blog/' }} />
React.createElement('link', null, 'https://reactjs.org/blog/');

// Invariant Violation: link is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.

This is a correct assumption to make for 100% of all browser front-ends.

What is the proposed new behavior?

In the exceptional case of generating SGML-like code (likely server rendered), it may become necessary to override the default behaviour of these whitelisted HTML void elements. For example, RSS uses the link tag to denote the site's root URL and the URL for individual item entries. The actual value is a TextNode of the link tag and will cause the above error when trying to generate via a React component.

My proposed solution would add a new, lengthily named property that bypasses the void element check and allows for these items to be rendered with children/dangerouslySetInnerHTML. Example implementation:

<link allowInvalidVoidElementChildren={true}>https://reactjs.org/blog/</link>
<link allowInvalidVoidElementChildren={true} dangerouslySetInnerHTML={{ __html: 'https://reactjs.org/blog/' }} />
React.createElement('link', { allowInvalidVoidElementChildren: true }, 'https://reactjs.org/blog/');

// <link>https://reactjs.org/blog/</link>

Much in the vein of dangerouslySetInnerHTML, the property is named such that it:

  • Likely avoids name collisions from any existing consumer code
  • Makes it explicit that setting this flag causes non-standard and potentially undesirable effects for most usual use cases

This feature should be implemented in a way that all existing unit tests pass without alteration. New unit tests would be added to ensure that the new functionality works as intended.

The following files have been identified as the places to implement this feature:

  • packages/react-dom/src/shared/assertValidProps.js
  • packages/react-dom/src/__tests__/ReactDOMComponent-test.js
  • packages/react-dom/src/shared/DOMProperty.js

Did this work in previous versions of React?

If this worked in previous versions of React, it was likely a bug.

@aweary

This comment has been minimized.

Member

aweary commented Mar 18, 2018

In the exceptional case of generating SGML-like code (likely server rendered), it may become necessary to override the default behaviour of these whitelisted HTML void elements. For example, RSS uses the link tag to denote the site's root URL and the URL for individual item entries.

ReactDOM and ReactDOMServer aren't meant to be a generic SGML/XML-like renderers, their sole purpose is rendering to the DOM and outputting HTML, respectively. Adding escape hatches to get around this would run contrary to the intended purpose of the renderers, and open up a can of worms for all the other XML-like formats that users might want to output.

If you want to use React to render some other format you could consider using react-reconciler to create your own renderer. It's API is currently experimental, but it will be a suitable long-term solution for these cases.

Hope that helps!

@aweary aweary closed this Mar 18, 2018

@dxprog

This comment has been minimized.

dxprog commented Mar 18, 2018

I had a hunch that might be the case. Thanks for reviewing and the heads up on react-reconciler!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment