React-native-web Multi-Platform Setup using Expo 44 + Typescript

Viewed 233

What is the simplest way to implement Multi-Platform Setup for a component in Expo. I have tried mamy diferent ways.. it was working on web but it is failing on Native and failing with Jest & @testing-library/react-native. Ideally I would like the least amount of custom config etc (do not want to eject). I expect the file structure to look like this:

Component
|- index.tsx
|- Component.native.tsx
|- Component.web.tsx

I am not sure how to do the index.tsx. I saw someone say something like this would work:

// index.tsx
// @ts-ignore
export { default } from "Component"

this didn't work so I did

// index.tsx
// @ts-ignore
export { default } from "./Component"

This worked for web, but the jest test said

Cannot find './Component'

However, Jest was able to find:
        './Component.mobile.tsx'
        './Component.web.tsx'

I tried:

// index.tsx
// @ts-ignore
import Component from "./Component";
export default Component

and the tests was the same

and the native emulator said:

Unable to resolve module ./Component

I tried using lazy loading but this does not work on web.

import { lazy, Suspense } from "react";
import { Platform } from "react-native";
import Loading from "../../components/Loading";
import { ComponentType } from "./types";

const Web = lazy(() => import("./Component.web"));
const Mobile = lazy(() => import("./Component.mobile"));

const Component: ComponentType = (props) => {
  const isWeb = Platform.OS === "web";
  return (
    <Suspense fallback={<Loading message="Loading Component" />}>
      {isWeb ? <Web {...props} /> : <Mobile {...props} />}
    </Suspense>
  );
};

export default Component

Questions

  1. how to use diferent files for components depending on platform (exlude other files from build)
  2. how to make it ok with ts in vscode

Using Expo 44. Thanks

1 Answers

I would use named exports. So begin by having the same component name in both files. Next I would have one file called Component.tsx and the other Component.native.tsx. That will be enough to allow the bundler to pull the native for native and the other for non-native (in other words web). That should be all you need.

Related