StencilJS 向 React 发出事件

StencilJS emit event to React

我有一组嵌套的 StencilJS 组件。我想将一个函数附加到我的嵌套组件,以便我的托管父组件的 React 应用程序可以读取。

例子

<pw-actionbar
   actions={getActions}
/>

在这个操作栏组件中,我有另一个嵌套的 button 组件。看起来像这样

return (
  <Host>
    <div class="container">
      {
        // iterate through array
        this.actions.map((action) => {
          // take object.icon and make an icon
          const XmlIcon = `${action.icon}`;
          ==> I WANT A FUNCTION ON PW-BUTTON THAT PASSES 'action' which my react app reads
          return <pw-button-side-menu 
            // shade the selected pages button
            isselected={action.onpage ? 'selected' : 'notselected'}
            class="displace"
          >
            <span slot="label">{action.name}</span>
            <i slot="icon">
              <XmlIcon
                class="icon-position"
                fillcolor={this.iconfillcolor}
                strokecolor={this.iconstrokecolor}/>
            </i>
          </pw-button-side-menu>
        })
      }
    </div>
  </Host>
 );
}

我的 React 应用有一些组件

functionEmittedFromPwButton(action) {
  console.log(action) <=== I WANT THIS TO WORK IN MY REACT APP WHICH IS EMITTED FROM THE PW-BUTTON COMPONENT NESTED IN THE PW-ACTIONBAR COMPONENT
}
 return (
<MyComponent>
<pw-actionbar actions={getActions}/> <=== that takes an array of objects. I want to capture the 'action' object emitted by the pw-button nested in this component in my react app
</MyComponent>
)

我已经尝试了各种不同的方法来尝试从模板中发出对象以做出反应

在模板方面

  import { Component, h, Host, Prop, Event, EventEmitter } from "@stencil/core";
@Component({
  tag: "pw-actionbar",
  styleUrl: "pw-actionbar.scss",
  shadow: true,
})
export class PwActionbar {
  @Prop() actions: any = [];
  @Prop() iconfillcolor: "white" | "black" = "white";
  @Prop() iconstrokecolor: "white" | "black" = "white";
  @Event() emitAction: EventEmitter;

  render() {
    const handleClick = (action) => {
      this.emitAction.emit(action);
    };
    return (
      <Host>
        <div class="container">
          {
            // iterate through array
            this.actions.map((action) => {
              // take object.icon and make an icon
              const XmlIcon = `${action.icon}`;
              // cast the button
              return (
                <pw-button-side-menu
                  // shade the selected pages button
                  isselected={action.onpage ? "selected" : "notselected"}
                  class="displace button-lines"
                  onClick={() => handleClick(action)}
                >
                  <span slot="label">{action.name}</span>
                  <i slot="icon">
                    <XmlIcon
                      class="icon-position"
                      fillcolor={this.iconfillcolor}
                      strokecolor={this.iconstrokecolor}
                    />
                  </i>
                </pw-button-side-menu>
              );
            })
          }
        </div>
      </Host>
    );
  }
}

在反应方面

const handleAction = async (action, history, i18n) => {
  Metrics.track("Changed Page", { action });
  if ("sign-out" === action) {
    await authActions.logout();
    history.push(`/${i18n.locale}`);
  } else if ("help-desk" === action) {
    history.push(`/${i18n.locale}/zendesk`);
  } else if ("advisors" === action) {
    pageActionsObjAdmin[0].onpage = true;
    history.push(`/${i18n.locale}/admin/advisors`);
  } else if ("users" === action) {
    pageActionsObjAdmin[1].onpage = true;
    history.push(`/${i18n.locale}/admin/users`);
  } else if ("forecast" === action) {
    pageActionsObjAdmin[3].onpage = true;
    history.push(`/${i18n.locale}/admin/forecast`);
  } else if ("stats" === action) {
    pageActionsObjAdmin[4].onpage = true;
    history.push(`/${i18n.locale}/admin/stats`);
  }
};

const Layout = ({ children }) => {
  const { i18n } = useLingui();
  const [, setContext] = useContext(StripeErrorContext);

  const history = useHistory();

  useEffect(() => {
    const listener = (e) => {
      // set page button to be "Active"
      pageActionsObjAdmin.forEach((element) => {
        element.onpage = false;
      });
      handleAction(e.detail.page, history, i18n, setContext);
    };

    // listen for events emitted form the action bar
    document.body.addEventListener("emitAction", listener);

    return () => {
      document.body.removeEventListener("emitAction", listener);
    };
  }, []); // eslint-disable-line

  // refs for the actionbar
  const elementRef = useRef(null);
  useEffect(() => {
    if (elementRef.current !== null) {
      elementRef.current.actions = pageActionsObjAdmin;
    }
  }, [elementRef]);

  return (
    <Wrapper>
      <Header />
      <BodyLayout>
        <pw-actionbar
          ref={(el) => (elementRef.current = el)}
          style={{ paddingTop: "56px", zIndex: "99" }}
          class="action-bar"
        />
        <div className="main-layout" style={{ width: "100%" }}>
          {children}
        </div>
      </BodyLayout>
    </Wrapper>
  );
};

export default Layout;