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

React error with child React Web Components #114

Closed
stevenalanstark opened this issue Jun 2, 2023 · 10 comments
Closed

React error with child React Web Components #114

stevenalanstark opened this issue Jun 2, 2023 · 10 comments

Comments

@stevenalanstark
Copy link

stevenalanstark commented Jun 2, 2023

Warning: Attempted to synchronously unmount a root while React was already rendering. React cannot finish unmounting the root until the current render has completed, which may lead to a race condition.

This error occurs when I try to add a react web component as a child of another web component, and it does not matter if it's the same component or another one. for example, these both cause the error:

    <p>
      <stepper-component title="Stepper Button-Child test">
        <button-element label="DEMO BUTTON"></button-element>
      </stepper-component>
    </p>
    <p>
      <stepper-component title="Stepper Self-Child test">
        <stepper-component title="Child Stepper"></stepper-component>
      </stepper-component>
    </p>

I'm using React 18.2.0

NOTE: I did try to use slots, but there was no change in the behaviour, so in this example I am just using {children} in the react component

@zerico007
Copy link
Contributor

Hi, slots is the ideal way to render children for a web component so I suggest using that. Concerning the error, you need to define a shadowRoot for the parent WC using the option of shadow: "open" or shadow: "closed". For example:
const StepperWC = r2wc(StepperComponent, { props: { title: "string" }, shadow: "open" });
customElements.define('stepper-component', StepperWC);

@stevenalanstark
Copy link
Author

@zerico007 - thank you for the suggestion, however setting the shadow root on or off does not resolve the issue.

this appears to be an order of operations issue that has to do with rendering

@zerico007
Copy link
Contributor

hmm can you share the implementation details for your components so I can poke around?

@zerico007 zerico007 reopened this Jun 5, 2023
@stevenalanstark
Copy link
Author

@zerico007 - Using slots or not just helps with controlling the location of the content, if it were regular HTML that would be fine, but here I am illustrating the issue with a child web component.

I have modified the sandbox demo to illustrate the issue, note that the component should be rendered twice, once as a parent and once as a child.

https://codesandbox.io/s/example-mui-button-forked-z68inn?file=/public/index.html

@zerico007
Copy link
Contributor

this implementation won't work without using slots. see my implementation below.

https://codesandbox.io/s/example-mui-button-forked-wj5e0h

@stevenalanstark
Copy link
Author

@zerico007 - very interesting.

I see now that I had the slot name wrong in my local test, and it is working after fixing that bit.

Can I ask why does a slot behave differently than children?

It is worth noting that though this does work, it is not ideal since it breaks regular DOM principals

@zerico007
Copy link
Contributor

zerico007 commented Jun 5, 2023

children is a React principle. To get the same implementation with web components, the slot HTML tag has to be used. it is a native HTML tag that can also be used when creating atemplate in HMTL. It's also how Vue allows you to insert "children" into a component since Vue components are created using a template.

@stevenalanstark
Copy link
Author

stevenalanstark commented Jun 6, 2023

that is a very big deviation from W3C DOM spec, which is very important that this is clear for all developers that use this. I would suggest adding this near the top of the ReadMe, along with including a working sandbox example.

see: https://www.w3schools.com/jsref/prop_element_children.asp

Thank you for all your help, I'm happy that there is a way around this limitation.

@zerico007
Copy link
Contributor

slots are a part of the web component technology suite and standard. you can access the children of a slot using slot.assignedNodes() or slot.assignedElements(). Creating a custom web component or a template that will render children, requires using slots. You can read more here

@stevenalanstark
Copy link
Author

@zerico007 - oh thank you for that, I didn't know that it was part of the base web component spec, I thought it was a react thing. Learn something new every day. cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants