在React中使用TypeScript为lit web组件添加函数:

huangapple go评论83阅读模式
英文:

Adding functions to lit web components in react with typescript

问题

我创建了一个在lit中制作的Web组件,它接受一个函数作为输入属性,但该函数未能从React组件中触发。

import React, { FC } from 'react';
import '@webcomponents/widgets';
declare global {
namespace JSX {
interface IntrinsicElements {
'webcomponents-widgets': WidgetProps
}
}
}
interface WidgetProps extends React.DetailedHTMLProps<React.HTMLAttributes, HTMLElement> {
var1: string,
successCallback: Function,
}
const App = () => {
const onSuccessCallback = () => {
console.log("在此添加一些逻辑");
}
return()
}


如何在React组件中触发该函数?我在Vue 3中尝试了这个,结果如预期。

我漏掉了什么吗?
英文:

I have a web component i created in lit, which takes in a function as input prop. but the function is not being triggered from the react component.

import React, { FC } from &#39;react&#39;;
import &#39;@webcomponents/widgets&#39;
declare global {
    namespace JSX {
        interface IntrinsicElements {
            &#39;webcomponents-widgets&#39;: WidgetProps
        }
    }
}
interface WidgetProps extends React.DetailedHTMLProps&lt;React.HTMLAttributes&lt;HTMLElement&gt;, HTMLElement&gt; {
    var1: string,
    successCallback: Function,
}
const App = () =&gt;{
   const onSuccessCallback = () =&gt;{
       console.log(&quot;add some logic here&quot;);
   }
   return(&lt;webcomponents-widgets var1=&quot;test&quot; successCallBack={onSuccessCallback}&gt;&lt;/webcomponents-widgets&gt;)
}

How can i trigger the function in react component? I have tried this is vue 3 and is working as expected.

Am i missing something?

答案1

得分: 2

如在此答案中指出,React 目前不正确地处理 Web 组件的函数属性。

虽然可以使用 ref 来以命令方式添加函数属性,但我建议在 Web 组件中更符合惯例的做法是不将函数作为属性传递,而是让 Web 组件在“成功”时分派事件,然后由使用者编写事件处理程序。

因此,<webcomponents-widgets> 的实现,而不是调用

this.successCallBack();

可以改为

const event = new Event('success', {bubbles: true, composed: true});
this.dispatchEvent(event);

然后,在您的 React 组件中,您可以添加事件侦听器。

const App = () => {
  const widgetRef = useRef();
  const onSuccessCallback = () => {
    console.log("在此添加一些逻辑");
  }
  useEffect(() => {
    widgetRef.current?.addEventListener('success', onSuccessCallback);
    return () => {
      widgetRef.current?.removeEventListener('success', onSuccessCallback);
    }
  }, []);
  return(<webcomponents-widgets var1="test" ref={widgetRef}></webcomponents-widgets>);
}

@lit-labs/react 包允许您包装 Web 组件,将其转换为 React 组件,以便以声明方式处理此类事件。

英文:

As pointed out in this answer, React does not handle function props for web components properly at this time.

While it's possible to use a ref to add the function property imperatively, I would suggest the more idiomatic way of doing things in web components is to not take a function as a prop but rather have the web component dispatch an event on "success" and the consumer to write an event handler.

So the implementation of &lt;webcomponents-widgets&gt;, instead of calling

this.successCallBack();

would instead do

const event = new Event(&#39;success&#39;, {bubbles: true, composed: true});
this.dispatch(event);

Then, in your React component you can add the event listener.

const App = () =&gt; {
  const widgetRef = useRef();
  const onSuccessCallback = () =&gt; {
    console.log(&quot;add some logic here&quot;);
  }
  useEffect(() =&gt; {
    widgetRef.current?.addEventListener(&#39;success&#39;, onSuccessCallback);
    return () =&gt; {
      widgetRef.current?.removeEventListener(&#39;success&#39;, onSuccessCallback);
    }
  }, []);
  return(&lt;webcomponents-widgets var1=&quot;test&quot; ref={widgetRef}&gt;&lt;/webcomponents-widgets&gt;);
}

The @lit-labs/react package let's you wrap the web component, turning it into a React component so you can do this kind of event handling declaratively.

答案2

得分: 1

React 对 Web 组件的处理不如其他框架那么好(但计划在将来改进)。

这里发生的情况是,您的 successCallBack 参数被转换为字符串。您需要在 Web 组件上设置一个引用,并从 useEffect 中设置 successCallBack

const App = () => {
   const widgetRef = useRef();
   const onSuccessCallback = () =>{
       console.log("在这里添加一些逻辑");
   }
   useEffect(() => {
      if (widgetRef.current) {
         widgetRef.current.successCallBack = onSuccessCallback;
      }
   }, []);
   return(<webcomponents-widgets var1="test" ref={widgetRef}></webcomponents-widgets>)
}
英文:

React does not handle Web Components as well as other frameworks (but it is planned to be improved in the future).

What is happening here is that your successCallBack parameter gets converted to a string. You need to setup a ref on your web component and set successCallBack from a useEffect:

const App = () =&gt; {
   const widgetRef = useRef();
   const onSuccessCallback = () =&gt;{
       console.log(&quot;add some logic here&quot;);
   }
   useEffect(() =&gt; {
      if (widgetRef.current) {
         widgetRef.current.successCallBack = onSuccessCallback;
      }
   }, []);
   return(&lt;webcomponents-widgets var1=&quot;test&quot; ref={widgetRef}&gt;&lt;/webcomponents-widgets&gt;)
}

huangapple
  • 本文由 发表于 2023年2月6日 15:54:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75358622.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定