Element Framework

React Guide

This guideline uses create-react-app, React v17.0.2 and Yarn v1.22.10.

Install yarn.

npm install -g yarn

Initialize your project

To create a new app, you may choose one of the following methods:

npx

npx create-react-app my-app

yarn

yarn create react-app my-app

It will create a directory called my-app inside the current folder. Inside that directory, it will generate the initial project structure and install the required dependencies.

Serve your app to check if the project is created correctly.

cd my-app
yarn start

Install EF elements and themes

Installs elements and themes.

yarn add @refinitiv-ui/elements
yarn add @refinitiv-ui/halo-theme

Import elements that you want to use and theme in src/index.js. You can also import EF components and themes anywhere in react components but for the simplicity we'll import all at once.

import '@refinitiv-ui/elements/lib/loader';
import '@refinitiv-ui/elements/lib/button';
import '@refinitiv-ui/elements/lib/panel';
import '@refinitiv-ui/elements/lib/text-field';
import '@refinitiv-ui/elements/lib/password-field';

import '@refinitiv-ui/halo-theme/dark/imports/native-elements';
import '@refinitiv-ui/elements/lib/loader/themes/halo/dark';
import '@refinitiv-ui/elements/lib/button/themes/halo/dark';
import '@refinitiv-ui/elements/lib/panel/themes/halo/dark';
import '@refinitiv-ui/elements/lib/text-field/themes/halo/dark';
import '@refinitiv-ui/elements/lib/password-field/themes/halo/dark';

Use EF elements to create a simple login page. Replace the content in src/App.js with the following code.

import React, { useState } from 'react';
import './App.css';

function App() {
  const [title, setTitle] = useState('Hello!');
  const [loading, setLoading] = useState(false);

  function login() {
    setLoading(true);

    setTimeout(() => {
      setTitle('Done!');
      setLoading(false);
    }, 2000);
  }

  return (
    <ef-panel id="login-page" spacing>
      {loading ? (
        <ef-loader></ef-loader>
      ) : (
        <>
          <h1>{title}</h1>
          <ef-text-field placeholder='Username'></ef-text-field>
          <ef-password-field placeholder='Password'></ef-password-field>
          <div id="button-group">
            <ef-button onClick={login}>Login</ef-button>
            <ef-button>Cancel</ef-button>
          </div>
        </>
      )}
    </ef-panel>
  );
}

export default App;

And in src/App.css

#login-page {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 450px;
  height: 200px;
  margin: 40px auto;
}

#button-group {
  margin: 10px 0;
}

Finally, starting your app and it should automatically open http://localhost:3000/ on your default browser.

yarn start

Using web components in React

Web components can be used in React just like any other HTML elements. However, there are a few differences to note.

class vs className

Web component uses class attribute instead of className.

function Panel() {
  return (
    <ef-panel class="container">
      ...
    </ef-panel>
  );
}

Attributes

Boolean

Boolean attributes such as disabled, readonly, checked are set by the presence of the attribute itself, not the value. To represent a false value in JSX, set the attribute's value to undefined or null or simply remove the attribute. This behavior is the same as HTML specifications.

Regardless of the value, the following code will disable the ef-text-field.

<ef-text-field disabled></ef-text-field>
<ef-text-field disabled="true"></ef-text-field>
<ef-text-field disabled="false"></ef-text-field>
<ef-text-field disabled={true}></ef-text-field>
<ef-text-field disabled={false}></ef-text-field>

The following will omit disabled attribute and enable ef-text-field.

<ef-text-field></ef-text-field>
<ef-text-field disabled={undefined}></ef-text-field>

Array and Object

React only allows primitive data to be passed through attributes. For Array and Object, you can either pass data through element's property or use JSON.stringify() to parse the data before passing to attribute.

<ef-sparkline data={JSON.stringify([-2, -3, 4])}></ef-sparkline>

or

function SparklineChart() {
  const chartRef = React.useRef();
  React.useLayoutEffect(() => {
    if (chartRef.current) {
      chartRef.current.data = [-2, -3, 4];
    }
  }, [chartRef]);
  return <ef-sparkline ref={chartRef}></ef-sparkline>;
}

Events

Use ref to access and store DOM element, then add an event-listener inside useLayoutEffect which fires synchronously after the DOM mutation (or componentDidMount in class component). Finally, don't forget to unsubscribe from event-listener when component unmounts.

function App() {
  const textFieldRef = React.useRef();
  const [value, setValue] = React.useState('');

  React.useLayoutEffect(() => {
    const handleChange = (event) => {
      setValue(event.detail.value);
    };

    const { current } = textFieldRef;

    if (current) {
      current.value = value; // update element's value
      current.addEventListener('value-changed', handleChange);
    }

    return () => current.removeEventListener('value-changed', handleChange); // unsubscribe
  }, [value, textFieldRef]);

  return <ef-text-field ref={textFieldRef}></ef-text-field>;
}

Develop the application on IE11 (or legacy browsers)

Legacy browser does not support Web Component and ES2015.

By default create-react-app does not provide the polyfills. You will have to configure your application to include all necessary polyfills so your app can work on legacy browsers. Polyfills should load at earliest, imports the polyfills at the very top of src\index.js and followed by elements and themes.

yarn add react-app-polyfill
yarn add @refinitiv-ui/polyfills

@refinitiv-ui/polyfills/minimal provides polyfills for custom components without any polyfills for ES2015 features so you can use it with react-app-polyfill.

For more details about react-app-polyfill, see here.

Import them before EF polyfills.

import 'react-app-polyfill/ie11';
import '@refinitiv-ui/polyfills/minimal';

Once you've included the polyfills, it's still not working when you open your app, http://localhost:3000/, on IE11. This is because development environment is set to run in modern browsers as it's easier for developers to debug.

To run a development server on IE11, open package.json and add IE 11 to development section at broswerslist configuration.

  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version",
+     "IE 11"
    ]
  }

For production build, the configuration already supports IE11. You can see the list of browsers it covers by running command:

npx browserslist

You'll see that IE11 is already included the list. You can update the configuration to be suitable with browsers that your app needs to support. For more detail, see browserslist.

That's all for now. Contact us at RefinitivUIDev@refinitiv.com, if you need any extra help!