ant-design / cssinjs

https://ant-design.github.io/cssinjs
MIT License
236 stars 59 forks source link

Cache singleton causes problems with multi-StyleProvider apps (or WebComponents) #83

Open Psvensso opened 1 year ago

Psvensso commented 1 year ago

We use Lit WebComponents to structure our Micro/UI-Composition "widgets". In ant 4 we injected our styles and overrides in each WC´s head. The new StyleProvider however provides us with a convenient component={Element} props.

But when instantiating the WebComponent multiple times we see that Ant reuses the Context config and injects the style only in the first component (e.g. the config is a singleton).

Expected: The CSS to be injected in the specified Element as specified for each element (in our case each WC's shadowroot).

Actuall: Injected in the first provided Element and ignoring the additional configs.

Repro: https://stackblitz.com/edit/react-ts-isblup?file=index.tsx,index.html

Similar to #28

@felixschorer Did you not come across this problem?

Psvensso commented 1 year ago

I actually found a "workaround" directly after writing this. You can provide your own cache instance via the cache prop and then it works as expected. The stackblitz now contains the "workaround".

I guess this is a bit of a special case, if it's in the docs its good enought for me. Feel free to close if by design.

https://github.com/ant-design/cssinjs/blob/9f2a6c7cfbe5650d21316df1d4983330b5ed7e93/src/StyleContext.tsx#L106

felixschorer commented 1 year ago

@Psvensso No, we haven't encountered that problem yet. Our use case is different. Each consumer only embeds one of our webcomponents as they are highly tailored to their use case.

Psvensso commented 1 year ago

@felixschorer yeap, we mostly have the same where we only have one WebComponent that wraps a large peice of functionality so this was not discovered untill now.

In my real use-case i had two WC's that were delivered in one JS bundle and therefore shared the ant dependencie then the styling was only applied to one of them. Since the "default" cache is a singleton in the js module.

import { createCache, StyleProvider } from '@ant-design/cssinjs';
<StyleProvider cache={createCache()}>

Perhaps it would be a good idéa to create a new cache instance for the provider if the container prop is used?

@zombieJ

trionfordring commented 1 year ago

I had the same problem. I am developing a low-code editor which renders its canvas in ShadowDom and therefore cannot use an external stylesheet. I solved the problem in this way:

<Container>
  <StyleProvider container={shadowRoot} cache={privateCache}>
      <ComponentEditorFrame />
  </StyleProvider>
</Container>

But I'm worried that this solution will cause some bugs, as I see that the source code of this library contains a lot of document.queryAll.