single-spa-angular icon indicating copy to clipboard operation
single-spa-angular copied to clipboard

Parcel ends up duplicated in the body of the document if props are updated

Open fcano-ut opened this issue 2 years ago • 2 comments

Demonstration

This is the repository to reproduce the issue: https://github.com/fcano-ut/single-spa-test

In the repo you can start three servers:

  • react-microfrontend (to test using a microfrontend)
  • angular-host (where the issue happens)
  • react-host (to check that the issue does not happen there, so it must be due to this package and not something about the microfrontend)

The key to reproduce the issue is to first mount the parcel, and then update any of it's props. I'm using this code in the Angular host (https://github.com/fcano-ut/single-spa-test/blob/main/packages/angular-host/src/app/app.component.ts#L13-L29)

export class AppComponent {
  title = 'angular-host';

  public customProps: any = {
    message: "I'm passing a prop on mount!"
  };

// ...
  ngOnInit() {
    // ...
    window.setTimeout(() => {
      this.customProps = {
        message: "I'm updating props!",
      };
    }, 100);

The react microfrontend simply prints the message like so: {props.name} is mounted! and it's saying: {props.message}

If we load this in the browser, it's clear that the microfrontend loads twice, the second time at the end of the page:

MFE loading twice

If we stop exporting the update function on the microfrontend side (removing it from here), it loads only where it should, but it doesn't receive updates on props.

Also we can just stop updating props to get the same result, it renders correctly but you cannot update props:

Meanwhile, the React host works correctly as it should, so I assume the issue is in the Angular Parcel component

https://github.com/single-spa/single-spa-angular/assets/97605542/6c04f11e-2465-4cbe-bee8-b9accde2269b

Expected Behavior

I expect the Angular host app to work as the React host app: first load the microfrontend, then update it in place

Actual Behavior

The Angular host first renders the microfrontend with initial props where it should, but then updates it and duplicates the microfrontend, appending it to the end of the body component, with the new props. Two versions of the microfrontend end up in the page.

(I didn't include this in the reproduction example, but in our real world scenario we also have navigation using Angular router, and the duplicated microfrontend doesn't unmount when the route changes)

fcano-ut avatar Oct 18 '23 09:10 fcano-ut

Just for future reference, this was first included as an issue in the single-spa-react package, but that issue was closed when I found out the cause of the issue is here. The previous issue was: https://github.com/single-spa/single-spa-react/issues/194

fcano-ut avatar Oct 18 '23 09:10 fcano-ut

Comparing the Angular and React implementation, React passes this when updating (see here):

update({
  ...parcelProps,
  domElement,
})

But Angular doesn't pass domElement when updating, only when mounting (see here).

That could be the cause of the bug?

fcano-ut avatar Oct 18 '23 13:10 fcano-ut