Introduction
Last week Meta open-sourced a new library called react-strict-dom
, its goal is to improve and standardize the way of writing React components for Web and Native. In this article, I'd like to go through the historical background of building a universal codebase that shares components between Web and Native, and how react-strict-dom
changes the way we can do it.
Historical background
As you may know React Native has different primitives for rendering UI than the Web, when you're a Web developer and you see basic RN components:
import { View, Text } from "react-native";
const App = () => {
return (
<View>
<Text>Hello, world!</Text>
</View>
);
};
it can seem a bit odd and hard to use at first. Also, it removes the ability to use UI libraries that are using Web primitives in React Native. Also migrating components from the Web takes a lot of time and is painful.
react-native-web
A few years ago React Native for Web was created by Nicolas Gallagher during the development of Twitter's Progressive Web App. RNW adds a compatibility shim which translates React Native's primitives into react-dom
ones, allowing us to render React Native components on the Web:
But this primitive comes with quite a few drawbacks:
- The shim implements a large surface area of fragmented APIs, and it needs to match React Native's non-standard implementations (e.g. events).
- The shim itself is quite big, which is not the best for modern web apps.
What is react-strict-dom
approach?
react-strict-dom
takes the opposite approach to React Native for Web
and it utilises Web APIs to render components. For this, it adds two small polyfills
which are responsible for translating its APIs to react-native
and react-dom
primitives. Here's a nice graph which shows how it work
in detail:
For now, not all APIs are polyfilled or built-in inside Native platforms but there's an ongoing effort to make so (here's a current compatability list with progress on supporting primitives).
Creating components with react-strict-dom
react-strict-dom
is powered by stylex which
is a new styling solution created by Meta that is already powering facebook.com in
production. It comes with the package under css
module. All the building
blocks with which we can build our app are available under
html
. This is how building UI with RSD looks like:
import React from "react";
import { css, html } from "react-strict-dom";
// Part of apps/examples/src/App.js
export default function App() {
return (
<html.div style={styles.div}>
<html.div data-testid="testid">div</html.div>
<html.span>span</html.span>
<html.p>paragraph</html.p>
<html.div />
<html.span>
<html.a href="https://google.com">anchor</html.a>,
<html.code>code</html.code>,<html.em>em</html.em>,
<html.strong>strong</html.strong>,
<html.span>
H<html.sub>2</html.sub>0
</html.span>
,<html.span>
E=mc<html.sup>2</html.sup>
</html.span>
</html.span>
</html.div>
);
}
// This is calling `stylex` under the hood
const styles = css.create({
div: {
paddingBottom: 50,
paddingTop: 50,
backgroundColor: "white",
},
});
react-strict-dom
is leveraging APIs that we know from the Web to build
universal apps.
Is <html.div>
a native component?
Yes, it is! The role of react-strict-dom
is to translate one universal API to platforms' primitives.
Also as we can read in React Native Principles blog post:
Our top priority for React Native is to match the expectations people have for each platform. This is why React Native renders to platform primitives. We value native look-and-feel over cross-platform consistency.
React Native goal is to create fully native apps, so with the new approach at the end of the day, we still have a fully native app, not a WebView, or anything else. We can easily check it by running example app inside the repository and by inspecting components with Xcode's View Hierarchy tool:
💡 For technical deep dive I really encourage you to read RFC by Nicolas: RFC: React DOM for Native (reduce API fragmentation)
Future
There's a lot of work to do, you can follow the current status in COMPATABILITY.md document inside repository, but it looks like having one primitive that most developers know from Web is the best choice to build universal apps.
Also what is worth noticing is that react-strict-dom
is powering teams at Meta in shipping features faster, to more platforms with fewer engineers 🚀 and it's the first cross-platform React solution which both targets Web and Native with the same components that Meta is directly investing into!
Summary
It's a really great move in the React ecosystem, it looks like react-strict-dom
is a successor of React Native Web and it will allow us to build universal apps with one codebase delivered to multiple targets using the platform's APIs without any compromises or performance issues. Thanks for reading! 🙌