There is a fairly popular site https://custom-elements-everywhere.com that shows how web components work in different frameworks. Almost all frameworks have a beautiful 100% result there, but React has a very alarming 71% there:
Many users look at this page and conclude that React does not only poorly support web components, but also the DOM API in general. Is it so? Is it really bad?
Let's figure it out!
Analyzing tests
The rating is calculated based on tests. This is where the result is shown . There are 15 tests in total, 7 of them are broken, hence we get such an unimportant rating. The following tests are broken:
attributes and properties
will pass array data as a property
will pass object data as a property
events
can declaratively listen to a lowercase DOM event dispatched by a Custom Element
can declaratively listen to a kebab-case DOM event dispatched by a Custom Element
can declaratively listen to a camelCase DOM event dispatched by a Custom Element
can declaratively listen to a CAPScase DOM event dispatched by a Custom Element
can declaratively listen to a PascalCase DOM event dispatched by a Custom Element
, , . . 71% , 90% 15% , - .
, - , . - Github:
" " ? .
:
<input type="checkbox" checked={checked} onChange={handleChange} />
. - :
<custom-checkbox checked={checked} onChange={handleChange} />
, on*
React . ( ) . , Sebastian MarkbΓ₯ge ( React) . :
, . , touch- , , , , "" , .. , .
, , . , , , . , . DOM-, _ _ , . DOM- (refs) .
, React DOM-, , React ( Concurrent mode), Refs API:
function CustomCheckbox({ checked, handleChange }) {
const ref = useRef();
useEffect(() => {
ref.current.addEventListener("change", handleChange);
return () => ref.current.removeEventListener("change", handleChange);
}, [handleChange]);
return <custom-checkbox ref={ref} />;
}
, custom-elements-everywhere? , . , , / .
?
" -" . , - JSX . , ( JSON.stringify) :
<user-view user="{user}" />
<!-- <user-view user="[object Object]" /> -->
. React DOM - . DOM- , . React- :
function UserView({ user }) {
const ref = useRef();
// user
useEffect(() => (ref.current.user = user), [user]);
return <user-view ref={ref} />;
}
/** @jsx h */
import { createElement } from "react";
import val from "@skatejs/val";
const h = val(createElement);
function Checkbox({ checked, handleChange }) {
// !
return <custom-checkbox checked={checked} onChange={handleChange} />;
}
, , , Google Developer Advocates , , . , React DOM ( ).
100%
100% . ? !. ( new CustomEvent('!')
)?
. , Angular . materials-components-web : MDCSlider:change
. Google (Angular) (Material design). , β DOM-.
, , - React 71% , Angular 100%. .
, . . , DOM β . , custom-elements-everywhere .
c custom-elements-everywhere, React DOM API -. , :
onChange React DOM- change. , [Github issue](https://github.com/facebook/react/issues/9657). React, React - , , onChange React β .
onFocus/onBlur . DOM API, focus, , . React , focusin. issue.
. , , . Portal API React-. DOM-, .
, . , , , React , () - DOM API , React (, react-focus-lock).
- . label. for id :
<label for="name"> </label>
<input id="name" name="firstName" />
. React :
const id = useUniqueId();
<Label for={id}> </Label>
<Input id={id} name="firstName" />
Label Input html- .
React, -:
<custom-label for="name"> </custom-label>
<custom-input id="name" name="firstName" />
Our text box is broken! The inner label tag was unable to communicate with the input tag because they are on different ShadowDOM instances. There is a proposal designed to solve this problem , but it is still in its infancy and does not work in any of the browsers (remember, web components have been developed for almost 10 years). And at the moment , it will not be possible to implement custom-label
it custom-input
in the form of web components, observing the accessibility requirements.
So think for yourself which technology is a real violation of web standards.