This package allows you to use React components in any environment, regardless of the framework or stack used, thanks to the technology of custom elements.
In the future, it will also allow the use of components developed with other libraries or frameworks.
Currently, this method only works with arrow function components.
Here is a very simple component example that supports props of different types as input (with possible default values).
import React from "react";
const AnyReactComponent = ({ type = "default value", mode, children, array = [], object, number, onUpdate }) => <>
<h2>AnyReactComponent</h2>
<p><strong>type : </strong> {type}</p>
<p><strong>mode : </strong> {mode}</p>
<p><strong>children : </strong> {children}</p>
<p><strong>array : </strong></p>
<ul>{array.map(item => (
<li key={item}>{item}</li>
))}</ul>
<p><strong>object : </strong>{object?.sub?.sub1}</p>
<p><strong>number : </strong>{number}</p>
<input type="text" onChange={onUpdate} />
</>
AnyReactComponent.displayName = "AnyReactComponent";
export default AnyReactComponent;
To make the previously created React component usable anywhere as a custom element, you need to define this custom element.
The method defineCustomElementReact
allows you to specify several essential elements:
type: string
It's highly recommended to prefix the custom element by a namespace to avoid conflicts with existing tags or directives.
type: React.FC
It's necessary to provide an arrow function component in this property.
type: string optional
The name of the custom element can be inferred from the name of the component passed in the component
property or its displayName
. You can, of course, customize it using this property.
type: string[] optional (required if the React component is not an arrow function)
This property indicates the list of props that you want to listen. Whenever one of the values changes, the custom element will re-render.
import { defineCustomElementReact } from '@axa-fr/everything-to-everywhere';
import AnyReactComponent from './AnyReactComponent';
defineCustomElementReact({
namespace: 'owc',
component: AnyReactComponent,
name: "a-component",
props: ["prop", "you", "want", "to", "listen"]
})
However, in a very simple case, you can omit the component name and the list of properties. This only works if:
- you want to map all the props
- your component destructures all of them explicitly. For example
({prop1, prop2, prop3})
would work but not({prop1, ...props})
or(props)
- your component is in the form of an arrow function component
- the target of the bundle is > ES6
- there is no modification on the destructuring of props in the bundle
You can, in all cases, set default values.
import { defineCustomElementReact } from '@axa-fr/everything-to-everywhere';
import AnyReactComponent from './AnyReactComponent';
defineCustomElementReact({
namespace: 'owc',
component: AnyReactComponent
})
In our previous example, the React component was called AnyReactComponent
(in Pascal case).
The custom element must comply with HTML standards and best practices, so it should have a namespace and be in kebab case.
Our component will be usable with the name owc-any-react-component
.
You will also need to pass all its required attributes:
<owc-any-react-component
mode="{{$ctrl.config.legacyContractBanner.bannerContent2}}"
children="{{$ctrl.replacementCompareUrl}}"
array="{{$ctrl.arrayForCE}}"
object="{{$ctrl.objectForCE}}"
number="12">
</owc-any-react-component>
Here, type
is not provided because it had a default value in its previous declaration.
This custom element is available wherever you can write HTML, whether in an AngularJS directive, JSX, etc.
Events are managed with callbacks that can be add after defining the custom element.
Let’s take our previous example and simplify it a little bit.
const AnyReactComponent = ({ type = "default value", mode, children, array = [], object, number, onUpdate }) => <>
...
<input type="text" onChange={onUpdate} />
</>
As a reminder, in our case, our component will be used with the tag owc-any-react-component
.
We will add our events by this way:
const $OwcAnyReactComponent = document.querySelector("owc-any-react-component");
$OwcAnyReactComponent.onUpdate = event => {
console.log("### onUpdate", event.target.value);
};
Event management occurs in several steps:
- Pass our
onUpdate
event as a prop of the React component - Call this method at the appropriate time (for example, as a callback for our
onChange
event of our input) in the React component - Retrieve our custom element where we want to manage the event
- Attach a new attribute to our recently retrieved custom element (with the same name as the prop passed in the React component, the parameters can be retrieved)
Off course, you can also manage event by the way you want, for example by dispatching custom event, that works very well too.