ionic-team / stencil

A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
https://stenciljs.com
Other
12.55k stars 784 forks source link

Virtual DOM bug: SSR don't put the content of the slots in correct place in CSR #2036

Closed patrickalima98 closed 1 year ago

patrickalima98 commented 4 years ago

Stencil version:

 @stencil/core@1.8.1

I'm submitting a:

[ x ] bug report [ ] feature request [ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior:

When I use any stencil components without Shadow Dom, and insert content for slots (default and named) the hydrate not put the content of slots in the correct place in SSR, the code from the SSR is OK, but the error start in the client side.

The code generated before Stencil Hydrate, here the render of the component is OK.

<my-component class="hydrated sc-my-component-h sc-my-component-s" s-id="1">
  <!--r.1-->
  <!--o.0.1-->
  <!--o.0.2-->
  <div c-id="1.0.0.0" class="sc-my-component sc-my-component-s">
    <!--s.1.1.1.0.-->
    <!--t.0.1-->
    Default slot
    <div c-id="1.2.1.1" class="end sc-my-component sc-my-component-s">
      <!--s.1.3.2.0.end-->
      <span c-id="0.2" slot="end">
        End slot
      </span>
    </div>
  </div>
</my-component>

image

The code after Stencil Hydrate, here the texts isn't in the correct place.

<my-component class="hydrated sc-my-component-h sc-my-component-s">
  <!--r.1-->
  <!---->
    Default slot

  <!----><span slot="end">
        End slot
      </span>
  <div class="sc-my-component sc-my-component-s">
    <!--s.1.1.1.0.-->
    <div class="end sc-my-component sc-my-component-s">
      <!--s.1.3.2.0.end-->

    </div>
  </div>
</my-component>

image

Expected behavior:

The default slot to display the "Default slot" text and the named slot to display the "End slot" span.

<my-component>
  <div>
    Default slot
    <div>
      <span>
        End slot
      </span>
    </div>
  </div>
</my-component>

Steps to reproduce:

$ git clone https://github.com/patrickalima98/stencil-slot-bug.git
$ cd stencil-slot-bug
$ npm i
$ node ./server.js
# Open your browser in http://localhost:3333

Related code:

import { Component, h } from '@stencil/core';

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: false,
})
export class MyComponent {
  render() {
    return (
      <div>
        <slot/>
        <div class='end'>
          <slot name='end'></slot>
        </div>
      </div>);
  }
}

Other information:

juliovedovatto commented 4 years ago

@patrickalima98 did you solved this issue? We are facing the same problem

patrickalima98 commented 4 years ago

Hi @juliovedovatto not yet. I think the problem is with Stencil, I couldn't find a solution. In my tests, Stencil generates a result in SSR and, after running the browser, applies hydration and changes many attributes and lines in the code. These changes are different from what VueJS expects, so it forces a new rendering.

dutscher commented 4 years ago

I have a another problem with slots where the same problem occurs. The slot moves to different positions or disappear after rerender.

See here https://github.com/ionic-team/stencil/issues/1968

Its definitive a Stencil vdom problem.

cheers

sajTempler commented 3 years ago

I'm using this workaround for this:

in render() method

      <section class="controls">
        <slot onSlotchange={this.slotChanged} name="thisVerySlotName" />
      </section>
  private slotChanged(e) {
    if (e.target.name === 'thisVerySlotName') {
      const el: HTMLElement = document.querySelector('div[slot]');
      el.style.display = 'grid';
    }
  }

and in global styles:

div[slot] {
  display: none;
}

this works just fine, slots are positioned correctly from the beginning till the end ;)

rwaskiewicz commented 1 year ago

Hey folks 👋

I'm having some trouble getting this to reproduce on my end. I'm able to run the steps provided in the issue summary:

$ git clone https://github.com/patrickalima98/stencil-slot-bug.git $ cd stencil-slot-bug $ npm i $ node ./server.js Open your browser in http://localhost:3333

And can see the issue there. However, I can't seem to get this to reproduce by trying to reverse engineer/create the component and it's stencil project configuration settings. That is, I'm trying to build a minimal TSX file/component to reproduce it (so that I can verify the bug and use that component for a test case), but the original source doesn't appear to be present in the reproduction cases provided. If anyone has one/or would be willing to build one out, the team and I would greatly appreciate it!

ionitron-bot[bot] commented 1 year ago

Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.

Please reproduce this issue in an Stencil starter component library and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.

If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.

For a guide on how to create a good reproduction, see our Contributing Guide.

ionitron-bot[bot] commented 1 year ago

Thanks for the issue! This issue is being closed due to inactivity. If this is still an issue with the latest version of Stencil, please create a new issue and ensure the template is fully filled out.

Thank you for using Stencil!