Loading

React

With an application built using the create-react-app script the easiest way to include the Discovery components library is to call defineCustomElements() from the index.js file. Note that in this scenario applyPolyfills is needed if you are targeting Edge or IE11.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { applyPolyfills, defineCustomElements } from '@senx/discovery-widgets/loader';

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

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

Following the steps above will enable Discovery web components to be used in React, however there are some additional complexities that must also be considered. https://custom-elements-everywhere.com/ contains a synopsis of the current issues.

Properties and Events

The largest deficiencies that React currently has when it comes to working with standard HTML Custom Elements is that properties that contain non-scalar data (that is, data that is not a string or number) are not passed properly and custom events are not handled properly. The solution to both of these problems is to wrap the Discovery Custom Element in a React component, obtain a ref to the Custom Element, and use the ref in order to set the non-scalar properties and add event listeners via addEventListener. Here is an example showing how this works for the property passing:

import React, { useRef, useEffect } from 'react';
import {Param} from '@senx/discovery-widgets';
import { iconPaths } from '../util';

const DiscoveryDashboard: React.FC<{ options: Param; url: string }> = ({ options, url }) => {
  const elementRef = useRef(null);
  return <discovery-dashboard options={options} url={url} ref={elementRef}></discovery-dashboard>;
};

export default DiscoveryDashboard;

In this example, there are two properties: options is an object and url is a string. Since url is a string it can be handled normally. However, the other two properties are non-scalar and must be set via the ref to the Custom Element. Wrapping the Custom Element as such prevents you from having to obtain a ref with every instance of discovery-dashboard that you may need since you will instead be using the DiscoveryDashboard React component as such:

<DiscoveryDashboard options={options} url={url}></DiscoveryDashboard>