Skip to content

React Native Web support

Maciej Jastrzebski edited this page Jan 9, 2024 · 1 revision

This page is a notebook about key findings regarding potential support for React Native Web.

RN vs RN Web comparison

RN Web renders HTML elements like <div> instead of typical RN host views like <View />, <Text />.

// Testing code
const renderer = TestRenderer.create(
  <View>
    <Text>Test</Text>
  </View>
);
expect(renderer.toJSON()).toMatchSnapshot();

// RN Output
<View>
  <Text>
    Test
  </Text>
</View>

// RN Web Output
<div
  className="css-view-175oi2r"
  dir={null}
>
  <div
    className="css-text-146c3p1"
    dir="auto"
  >
    Test
  </div>
</div>

This can be easily replicated by installing jest-expo package and applying Jest "preset": "jest-expo/universal".

The comparison above has been achieved using React Test Renderer, since RNTL's detectHostComponentNames() function throws error when running under web preset.

Ideal solution

React.js (web) has a mature testing solution in form of RTL, on which RNLT is modelled. However, as noted in our docs, RTL has much better testing environment due to usage of Jest DOM package, which is very reliable browser DOM simulation. In contrast, RNTL contains code simulating only the key aspects of RN env, sometimes in a very crude way.

Therefore, our recommendation so far, has been to test RN Web using a proper RTL setup. This has two major downsides:

  1. It's a more complex setup for the user
  2. It requires user to write and maintain two sets of tests: one for RN using RNTL, and another for RN Web using RTL.

In order to ease life of RN Web users, we could potentially include proper RN Web setup inside RNTL. The env setup could be modelled on Jest Expo package (or simply re-use it). That would solve pain no. 1.

In order to solve pain no. 2, we would have to be able to execute given test suit in both RN+RNTL and RN Web+RTL+Jest DOM setup. The easiest, but not easy, way to achieve it would be create a adapter/facade layer, the would expose the same familiar RNTL API to the user, but would internally translate it to RTL calls. This should be possible as, RNTL API is largely coherent with RTL API. There are some semantic differences between the queries which would need to be bridged by such RNTL adapter. E.g., RNTL exposes includeHiddenElements option which is an alias to hidden option in RTL, but RNTL exposes it on all queries, while on RTL it's only available on *ByRole queries.

Alternative approaches

  1. Recommend users to test the core RN (not yet translated to Web) using current RNTL. This is what we support now. It does provide a unified testing ground for RN apps, by mixing together various iOS and Android observed runtime behaviours

  2. Provide example setup for devs wanting to test RN Web using RTL+Jest DOM, but without ability to share testing code. Users would have to duplicate their tests manually. RTL testing code would be largely copy-paste from RNTL with minor tweaks, but that the burden of maintaining RNTL/RTL differences would be on the users.

  3. Create and maintain an external RNTL Web package, that would do support the API adaptation described above, in a similar way that RN Web exposes RN APIs. This could be maintained either by RNTL team or by some 3rd party with serious interest in RN Web support.

Considerations

The decision whether to pursue this effort inside RNTL should be based on the following factors:

  1. Demand from the users to test RN Web apps using more realistic Jest DOM setup
  2. Cost of creating and maintaining such adapter code