-
Notifications
You must be signed in to change notification settings - Fork 794
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
Can't use a Stencil library from a React + TS application #1636
Comments
Similar to your previous workaround, I have something set up for stencil 1+ for convenience I will post again here. for people struggling with this, I've gotten things working this way: Edit: Updated thanks to @sslotsky for figuring out the last bits for this solution. // register-web-components.ts
/* eslint-disable */
import { defineCustomElements, Components, JSX as LocalJSX } from 'stencil-library/dist/loader';
import { DetailedHTMLProps, HTMLAttributes } from 'react';
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
type StencilProps<T> = { [P in keyof T]: Omit<T[P], "ref"> };
type ReactProps<T> = {
[P in keyof T]: DetailedHTMLProps<HTMLAttributes<T[P]>, T[P]>
};
type StencilToReact<
T = LocalJSX.IntrinsicElements,
U = HTMLElementTagNameMap
> = StencilProps<T> & ReactProps<U>;
declare global {
export namespace JSX {
interface IntrinsicElements extends StencilToReact {}
}
}
defineCustomElements(window); // index.ts
// ...
import './register-web-components';
// ... eslint will shout about using declare global but this is keeping me going for now. gets auto complete working |
@Nibblesh thanks so much for this! Extremely helpful. There is one detail giving me trouble with this solution, though: we are using hooks, and when I use a |
@sslotsky could you put an example of what you would like to work? I don't fully understand the scenario without an example |
@Nibblesh sure 😄 const link = React.useRef<HTMLManifoldButtonLinkElement>(null);
if (link.current) {
link.current.addEventListener(MANIFOLD_BUTTON_LINK_CLICK, someUrl);
}
...
// somewhere inside render
<manifold-button-link ref={link} href={href} preserveEvent>
Go to all products
</manifold-button-link> |
FWIW, I do have something working, but I can't figure out a way to loop through the keys. type ToReact<T> = DetailedHTMLProps<HTMLAttributes<T>, T>;
declare global {
export namespace JSX {
interface IntrinsicElements {
'manifold-button-link': Components.ManifoldButtonLink &
ToReact<HTMLManifoldButtonLinkElement>;
}
}
} By doing it this way you are using just the interface defined in |
Maybe this might be usable for you // register-web-components.ts
import { defineCustomElements, JSX as LocalJSX } from 'stencil-library/dist/loader';
import { HTMLAttributes, DetailedHTMLProps } from 'react';
import { Omit } from 'types';
type StencilToReact<T> = {
[P in keyof T]?: Omit<DetailedHTMLProps<HTMLAttributes<T[P]>, T[P]>, 'className'> & {
class?: string;
} & T[P];
} ;
declare global {
export namespace JSX {
interface IntrinsicElements extends StencilToReact<LocalJSX.IntrinsicElements> {
}
}
}
defineCustomElements(window)
|
Not quite, see error below 😄 I think the
|
I won't know until you try it but maybe this // register-web-components.ts
/* eslint-disable */
import { defineCustomElements, JSX as LocalJSX } from 'stencil-library/dist/loader';
import { HTMLAttributes, DetailedHTMLProps } from 'react';
import { Merge, Omit } from 'ts-essentials';
type StencilToReactElements<T = LocalJSX.IntrinsicElements> = {
[P in keyof T]?: T[P] & Omit<DetailedHTMLProps<HTMLAttributes<T[P]>, T[P]>, 'className'> & {
class?: string;
};
} ;
type StencilToReactRef<T = HTMLElementTagNameMap> = {
[P in keyof T]: {
ref?: DetailedHTMLProps<HTMLAttributes<T[P]>, T[P]>['ref']
}
};
type StencilToReact<T = LocalJSX.IntrinsicElements, U = HTMLElementTagNameMap>= StencilToReactElements<T> & StencilToReactRef<U>;
declare global {
export namespace JSX {
interface IntrinsicElements extends StencilToReact {
}
}
}
defineCustomElements(window) |
This doesn't work either 😞 TypeScript still thinks that ((elm?: HTMLManifoldButtonLinkElement | undefined) => void) If it helps @Nibblesh, the component library in question is public, and the version I'm testing against for this issue is available as an alpha release. You could try rendering one of the elements and attaching a ref to it with the |
I gave it a crack this morning without the best luck. Spent ages on this and looking through the type defs as although your issues don't affect me yet I am sure it will be an issue for me at some point. That being said It might be possible to get this to work using a HoC. Supply the rest of the props to the web component as per normal, then wrap it in a HoC which clones the child and converts the react ref object into a compatible callback method and return the cloned element. I don't have the time to give this a try ATM but I'll come back to it when I have a chance. |
@Nibblesh I think I got it, modifying your most recent example a bit! import { Components, JSX as LocalJSX } from '@manifoldco/ui';
import { DetailedHTMLProps, HTMLAttributes } from 'react';
type StencilProps<T> = {
[P in keyof T]?: Omit<T[P], 'ref'>;
};
type ReactProps<T> = {
[P in keyof T]?: DetailedHTMLProps<HTMLAttributes<T[P]>, T[P]>;
};
type StencilToReact<T = LocalJSX.IntrinsicElements, U = HTMLElementTagNameMap> = StencilProps<T> &
ReactProps<U>;
declare global {
export namespace JSX {
interface IntrinsicElements extends StencilToReact {}
}
} |
@sslotsky awesome!! I felt like I was close but I'm glad to hear you figured it out! I am going to update my original answer with this =) edit: just to call this one out, it works with typescript 3.5+ but didn't work on the version I had on my project at the time which was 3.3.4. I might have been making it unnecessarily hard for myself to try and figure this out by not upgrading earlier |
Nice @Nibblesh! We were using 3.5.2, I suppose every one of these discussions should start with environment info 😅 Now, do you happen to know if there's a way for TypeScript to know about the HTML attributes that a Stencil component accepts? It seems like TypeScript allows me to add absolutely |
I think that seems like it should be happening during the compilation step (might be worth writing up a feature request), wherever they're writing out the definitions for the camel case stuff, they could run a regex to convert camel to dash and register the same value there. |
Have you tried using Ionics way of doing this? We're also using Stencil components in a React/Typescript library. I copied an older version of the |
Thanks @sslotsky and @Nibblesh! In my case this is what worked:
I needed to add If anyone has a problem with other unsupported HTML attribute you can also assign |
I set up a monorepo to experiment Stencil and React integration using the info in this thread. See https://github.com/jagreehal/react-stencil-dx. When I get time this week I going to follow up on the suggestion by @schadenn |
@sslotsky another happy dev :-) thanks for the tip! |
Thx @sslotsky and @adrian-marcelo-gallardo, same to me in an Ionic React app!
|
Maybe there is something in the bigger picture that I don't get. But why cannot generated types simply have an export of interface IntrinsicElements. The types are generated correctly and ready for use but simply not exported. Why? Example. If components.d.ts only could have an export in front of interface IntrinsicElements: //components.d.ts export interface IntrinsicElements { // dev.d.ts in my react project declare global { |
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! |
Reopening since this is still an issue as mentioned in #2729. |
Hey everyone, first of all, thank you so much for the patience. I want to better understand where this issue is at. Is the original repro case still effective? Or, can we get an updated repro case going to I can better understand the behavior here on Stencil v2 code? |
Hey there 👋 I apologize it took so long for someone on the team to acknowledge this issue. At this time, Stencil v1 and lower is no longer supported, and the original reproduction case is no longer hosted on GitHub. As a result, I'm going to close this issue. If this issue is still occurring in Stencil v4 and the latest version of the Stencil-React output target, can you please create a new issue for us with a minimal reproduction case? Thanks! |
Stencil version:
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 using a Stencil component library from a React + TS application, we receive type errors. Specifically:
Expected behavior:
I should be able to use my web components from a React + TypeScript application without
JSX.IntrinsicElements
type errors.Steps to reproduce:
npm i && npm start
Related code:
Other information:
The React project used to demonstrate the issue is using an alpha release of our component library. You can find that alpha release in this git tag if you wish to download the source code.
The alpha release uses
@stencil/[email protected]
, but we have had this problem with previous versions as well. Before Stencil 1 was released, we had a workaround for the issue, described here under the section labeled "TYPESCRIPT + JSX SETUP". This workaround no longer works.The text was updated successfully, but these errors were encountered: