See how Stencil fits into the entire Ionic Ecosystem ->
Stencil is part of the Ionic Ecosystem ->

React

create-react-appで構築されたアプリケーションにコンポーネントライブラリを含める最も簡単な方法は、index.jsファイルから defineCustomElements()を呼び出すことです。 EdgeまたはIE11を対象とする場合は、applyPolyfillsが必要であることに注意してください。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

// test-componentはnpmに公開されたWebコンポーネントの名前です。
// npmで公開:
import { applyPolyfills, defineCustomElements } from 'test-components/loader';

ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

applyPolyfills().then(() => {
  defineCustomElements();
});

上記の手順に従うと、ReactでWebコンポーネントを使用できるようになりますが、いくつか考慮が必要な問題があります。https://custom-elements-everywhere.com/ には、現在確認されている問題の概要が記載されています。

プロパティとイベント

標準のHTML Custom Elementの操作に関してReactが現在抱えている最大の欠点は、非スカラーデータ(文字列や数値ではないデータ)を含むプロパティが適切に渡されず、カスタムイベントが適切に処理されないことです。これらの問題を解決するためには、Custom ElementをReactコンポーネントでラップし、Custom Elementへのrefを取得します。そして、refを使用して非スカラープロパティを設定し、addEventListenerを介してイベントリスナーを追加することです。次は、プロパティの受け渡しでどのように機能するかを示す例です。

import React, { useRef, useEffect } from 'react';
import { Forecast } from '../models';
import { iconPaths } from '../util';

const DailyForecast: React.FC<{ forecast: Forecast; scale: string }> = ({ forecast, scale }) => {
  const elementRef = useRef(null);

  useEffect(() => {
    (elementRef.current as any)!.iconPaths = iconPaths;
    (elementRef.current as any)!.forecasts = forecast;
  }, [forecast]);

  return <kws-daily-forecast scale={scale} ref={elementRef}></kws-daily-forecast>;
};

export default DailyForecast;

この例では、3つのプロパティがあります。forecastはオブジェクトの配列、iconPathsはオブジェクト、scaleは文字列です。scaleは文字列なので通常通り扱えます。ただし、他の2つのプロパティは非スカラーなのでrefを介してCustom Elementに設定する必要があります。このようにCustom Elementをラップすると、次のようにDailyForecastReactコンポーネントを使用できるため、kws-daily-forecastのすべてのインスタンスでrefを取得する必要がなくなります。

<DailyForecast scale={scale} forecast={f}></DailyForecast>

Bindings

Manually wrapping all Custom Elements in a React Component is a good practice, but it gets tedious quickly.

With bindings the web components get wrapped in a React component and then immediately become available as React Components. Some of the advantages of doing this are that you get types for your components. One of the main issues with React is that react does not properly pass properties to web components. Out of the box React can only pass strings and numbers to components and it cannot listen to custom events. With the bindings the components appear as though they are React components and all properties get passed correctly including functions, objects, and arrays. The bindings also account for custom events by creating a prop called ‘on’. These allow React developers to interact with the web components as though they are React components.

Install

npm install @stencil/react-output-target --save-dev

Stencil Config setup

import { Config } from '@stencil/core';
import { reactOutputTarget } from '@stencil/react-output-target';

export const config: Config = {
  namespace: 'demo',
  outputTargets: [
    reactOutputTarget({
      componentCorePackage: 'component-library',
      proxiesFile: '../component-library-react/src/components.ts',
    }),
    {
      type: 'dist',
    },
  ],
};

componentCorePackage

This is the NPM package name of your core stencil package. In the case of Ionic we chose ‘@ionic/core’. This is the package that gets published that contains just your web components. This package is then used by the React package as a dependency

proxiesFile

This is the output file that gets generated by the outputTarget. This file should be referencing a different package location. In the example case we are choosing a sibling directory’s src directory. We will then create a React package that exports all components defined in this file.

Setup of React Component Library

There is an example component library package available on Github so that you can get started. This repo will likely live as a sibling to your Stencil component library. https://github.com/ionic-team/stencil-ds-react-template

Usage

import { DemoComponent } from 'component-library-react';
BackNext
Contributors