Per #2645250-179: [META] Start using reactive declarative JS programming for some new core admin UIs, this is a child issue to discuss one factor in a vdom library that might be important to us.

Problem/Motivation

Drupal does occasionally return non-single-node fragments from various places, and when code is required to add an extra <div> wrapper to force it into a single node, problems arise. #736066: ajax.js insert command sometimes wraps content in a div, potentially producing invalid HTML and other bugs is an example of a 7 year old issue where we're still struggling with this.

If we end up picking a library that has a single-root-node-per-component limitation, are we willing to accept the consequences of occasional wrapper tags polluting a theme's desired markup structure?

Proposed resolution

?

Remaining tasks

Discuss.

Comments

effulgentsia created an issue. See original summary.

benjy’s picture

I'm not sure I fully get this, if you are handwriting React components, you need a top-level wrapper, React developers would know this. Unlike the issue referenced (#736066) we'll never be generating the initial HTML on the server from Drupal?

Drupal generating HTML that we intend for React to then manage actually seems to me like it would be way more problematic.

psteeleidem’s picture

FWIW, with the latest release of Marko.js there is no limitation on the number of root nodes and no extra DOM nodes that will pollute the DOM will be added. A UI component can render a single DOM node, multiple DOM nodes, no DOM nodes, only text nodes, etc. Also, there is no limitation regardless of whether or not a UI component is rendered on the server (under Node.js) or in the browser.

Anonymous’s picture

And Polymer, and Aurelia... they all have this limitation.
But I don't see how that will be an issue since the component will be fully rendered on the first page load and on ajax request, I would assume, we would only return state changes(drupalSettings --> Flux) which would get re-rendered by the component(that's where the reactivity comes in), instead of the old way of replacing pure HTML.

I would assume each page component would be registered in the drupalSettings' "components" store and it would react to changes made to the store as in any other application.

dawehner’s picture

I can't judge whether this missing feature is an actual problem. Can't you write some wrapper components which returns multiple elements? The resulting HTML should be the same.

React has a limitation where a component's render function can only return a single root element. Therefore, I assume that libraries designed for React's API, such as Preact and Inferno, have the same limitation.

Note: As of react 0.16 this is no longer a limitation: https://github.com/facebook/react/issues/2127#issuecomment-318202889
On the other hand, this might not be implemented by the *react alternatives.

GrandmaGlassesRopeMan’s picture

@effulgentsia as of react 16 this is no longer an issue. What @dawehner said.

effulgentsia’s picture

It's still an issue for Vue.js though. Hence the reparenting of this in #6.

alexdoronin’s picture

For Vue — maybe some workarounds with "functional components" https://jsfiddle.net/of6z0nu4/
(https://vuejs.org/v2/guide/render-function.html#Functional-Components).

effulgentsia’s picture

Re #10, wow, that's cool! The functional: true is required though. Do you know if this is a by-design feature that functional components are allowed to do this? https://vuejs.org/v2/guide/migration.html#Fragment-Instances-removed does not mention it, nor can I find any other Vue docs that do. https://github.com/vuejs/vue/issues/5961#issuecomment-310895399 mentions it, but that comment is not from a maintainer, and the maintainer's reply is simply that it's on the roadmap but with no projected timeframe or issue link. He neither confirmed nor denied the comment about functional components having the escape hatch. If the escape hatch wasn't intentional, then I'm concerned it might get removed in a future release prior to full support across all types of components getting added.

effulgentsia’s picture

Also, React 16 allows returning bare text (e.g., return 'one';) and top-level text nodes alongside sibling elements (e.g., return [h('div', {}, 'one'), 'two'];). Whereas for Vue, the example in #10 seems to only work for an array of elements (no top-level text nodes allowed).

alexdoronin’s picture

Re: #11

Unfortunately I can't clarify the situation with functional components in Vue. I heard about this approach only from non-maintainers.

dawehner’s picture

Drupal does occasionally return non-single-node fragments from various places,

It would be nice to document instances of that. Maybe there are common patterns to be seen.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

jungle’s picture

> In 3.x, components now can have multiple root nodes!

https://v3.vuejs.org/guide/migration/fragments.html#_3-x-syntax

effulgentsia’s picture

Status: Active » Closed (outdated)

Yep! This is no longer a differentiator between React and Vue, so closing the issue.

Per #3170260: Decoupled Menus Initiative, the current plan is to build some components for both React and Vue, and to publish them on npm, thereby postponing by as long as we can the need to make either one a hard dependency of Drupal core.

However, if/when there's a compelling reason to make one or both of them a hard dependency, we can discuss doing so. #3201871: Document benefits/drawbacks of adding Vue as a core JS library is the current place to discuss that about Vue, and so far that hasn't crossed the threshold, because the Backbone replacement issues look like they can happen well enough with vanilla JS instead.