Skip to content
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

How to send children prop in the custom HTML element created #7

Closed
Abhishek-Rajendra opened this issue Oct 11, 2020 · 11 comments
Closed
Labels
accepted Accepted for development enhancement New feature or request

Comments

@Abhishek-Rajendra
Copy link

Abhishek-Rajendra commented Oct 11, 2020

Let say I want something inside the <text-x> Hi </text-x>, I tried using <text-x children="Hi"></text-x> both didn't work

@Abhishek-Rajendra Abhishek-Rajendra changed the title How to sent children prop in the custom HTML element created How to send children prop in the custom HTML element created Oct 11, 2020
@justinbmeyer
Copy link
Member

Can you share what your component looked like?

@linuxonrails
Copy link

linuxonrails commented Jan 21, 2021

Same problem.

Example component:

js/tsx:

import * as React from 'react';
import * as PropTypes from 'prop-types';

export const Foobar = (props) => {
  console.log({ props });
  return (
    <div>
      headingtitle prop: { props.headingtitle }
      <br />
      children prop:<br />
      { props.children }
    </div>
  );
}

Foobar.propTypes = {
  headingtitle: PropTypes.string,
  children: PropTypes.node,
};

export default Foobar;
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import reactToWebComponent from 'react-to-webcomponent';

import { Foobar } from 'common/components/Foobar';

const FoobarAsWebComponent = reactToWebComponent(Foobar, React, ReactDOM);
customElements.define('foo-bar', FoobarAsWebComponent);

HTML:

        <foo-bar headingtitle="Heading title prop">
          <p>Todo lo que ves en nuestro catálogo. Tenemos a la venta más de 24.000.000 de lotes de más de 20.000 vendedores distintos.</p>
        </foo-bar>

Screenshot:
Screenshot (18)

console.log: props: { headingtitle: "Heading title prop" }

@StormRaider2495
Copy link

StormRaider2495 commented Jan 28, 2021

I am having a similar issue. But its happening post build with the attribute passed to the custom element.
After build the value is not getting passed to the react component from index.html

halkeye added a commit to halkeye/react-to-webcomponent that referenced this issue Feb 2, 2021
@justinbmeyer
Copy link
Member

Thanks @linuxonrails for trying to summarize this for me. I'm not actually much of a react dev (much more of a webcomponent dev).

Just to confirm the expected behavior ... it seems like props.children is react's version of a shadow/light DOM concept.

Is props.children always static? Its fully rendered contents are always passed down to the child component?

@leanderseige
Copy link

Not sure if I understand the problem but I can set props like this:

window.addEventListener('DOMContentLoaded', (event) => {
  var root = document.getElementById("id")
  var mywc = document.createElement('mywc')
  mywc.settings = "settings"
  root.appendChild(mywc)
}

@kidroca
Copy link

kidroca commented Oct 12, 2021

@justinbmeyer

Is props.children always static? Its fully rendered contents are always passed down to the child component?

Not always

Sometimes children can be another component

<MyChildAcceptingComponent>
  <ChildComponent propA={valueA} />
</MyChildAcceptingComponent>
  • Some time the child can be statically evaluated
  • Some times propA will change and the child needs to be re-rendered
  • Some times the child might do something to cause itself to re-render (e.g. the child has own state)

It's also possible to use children as a function (depending on the author of the react component)

<MyChildAcceptingComponent>
  {
    (someValue) => {
      return (
        <div>{someValue}</div>
      )
    }
  }
</MyChildAcceptingComponent>

MyChildAcceptingComponent decides how to interact with children
The user of MyChildAcceptingComponent knows whether they should provide a function or a Node (node is <Child Component />) or multiple nodes Node[]
When it's a function - MyChildAcceptingComponent decides what parameters to call the function with


The most common case is the children is a Node but it's still not static

Typically React render cycle mounts root nodes (the parents) then leaf nodes - the outermost leaf would finish render first (the deepest child) and signal the parent that it's ready, then parent will be ready if it has no more children to render
In that sense children might be already evaluated to a static content by the time you need to use them to convert that content to web component. I don't know where in React you can hook to though

@kidroca
Copy link

kidroca commented Oct 12, 2021

Or maybe this will have nothing to do with React

I think we're expecting usage like this:

<my-web-component-grid>
  <custom-item>
     <h4>Something</h4>
     <span>Something<span>
  <custom-item>
<my-web-component-grid>

We're not using React code here so why should it matter? We just want to supply whatever comes out of <custom-item> as content to <my-web-component>
So if we've already figured out the rendering of <custom-item> it should render a web component that can be used in there

Is it possible to update the interface of reactToWebComponent so that there's an option regarding how we'd like to handle children or elements added as child nodes

Like

const FoobarAsWebComponent = reactToWebComponent(Foobar, React, ReactDOM, {
  children: (containerNode, contentNode) => {
     containerNode.replaceChildren(contentNode.cloneNode(true));
    
     // or
     containerNode.shadowRoot.replaceChildren(contentNode.cloneNode(true));

    // or something else 
  }
});

And there can be a simple case where we just provide children: true

const FoobarAsWebComponent = reactToWebComponent(Foobar, React, ReactDOM, {
  children: true
});

Which should add an unnamed slot in FoobarAsWebComponent so that any child nodes are added there


I think the word children makes more sense to React developers whereas slot or slots might be clearer for web-component authors

Unlike web components in React there's always only one slot - children.
It's not often the case to need more than one slot and there are different workarounds like passing multiple nodes and putting them at different places based on type or other conditions.

@christopherjbaker christopherjbaker added accepted Accepted for development enhancement New feature or request labels Jul 29, 2022
@christopherjbaker christopherjbaker removed their assignment Sep 23, 2022
@PtAuDev
Copy link

PtAuDev commented Feb 8, 2023

How is it going by now ?

@christopherjbaker
Copy link

This is something we are looking into, but I don't have any progress updates at the moment. It is requiring some exploration because React expects children to be jsx or other renderable content that it can turn into DOM nodes; there's no way to give it content that is already DOM nodes.

@bertrand-riviere
Copy link

Unless there is something I don't understand, having "DOM children" can be done as described in this article (using a "slot"):
https://gilfink.medium.com/wrapping-react-components-inside-custom-elements-97431d1155bd

@christopherjbaker
Copy link

@bertrand-riviere That does look promising! It will still require some exploration to integrate it in a generic way, but we'll be picking this up soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted Accepted for development enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

10 participants