Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Platform specific import component in react native with typescript

I am using react native with typescript. I have a component with the following structure

component
    - component.ios.tsx
    - component.android.tsx

Now I want to import the component. So, I am doing this:

import component from '../component/component';

But it says:

[ts] Cannot find module ../component/component

The location is correct. I need to add something to the tslint file to make it understand.

I also tried to do:

let component = require('../component/component');

This didn't give typescript error. But it gave a runtime error.

element type is invalid expected a string or a class/function but got undefined

Has anybody run into this issue? Thank you.

like image 700
Rishi Avatar asked May 16 '17 12:05

Rishi


People also ask

Is TypeScript compatible with React Native?

While React Native is built in Flow, it supports both TypeScript and Flow by default.

Which module in React Native detects the platform in which the app is running?

os. React Native provides a module that detects the platform in which the app is running. You can use the detection logic to implement platform-specific code.

What platforms support React Native?

React Native is an open-source UI software framework created by Meta Platforms, Inc. It is used to develop applications for Android, Android TV, iOS, macOS, tvOS, Web, Windows and UWP by enabling developers to use the React framework along with native platform capabilities.


2 Answers

One way of doing it, which is a bit annoying, is creating a declaration file with the same name.

component
- component.d.ts   <---
- component.android.tsx
- component.ios.tsx

then

import { file } from "../group/file";

Update: Another way of doing it is just omit the extension for one of them, then typescript will pick up the default one.

  • component.tsx
  • component.android.tsx

Android will pick up the specific android file, and iOS will default to normal one.

like image 142
Jacob Arvidsson Avatar answered Sep 29 '22 07:09

Jacob Arvidsson


With last version of React you can use Suspense and lazy to avoid over typings etc., for example if I want a component Touchable with specific code for iOS and Android, my structure will looks like that:

- Touchable
   - index.tsx
   - Touchable.android.tsx
   - Touchable.ios.tsx
   - types.d.ts
   

And on index.tsx the code will looks like that:

import React, { FunctionComponent, lazy, Suspense } from 'react';
import { Platform, View } from 'react-native';

import { TouchableProps } from './types.d';

const TouchableComponent = lazy(() =>
  Platform.OS === 'ios'
    ? import('./Touchable.ios')
    : import('./Touchable.android'),
);

const Touchable: FunctionComponent<TouchableProps> = (props) => {
  return (
    <Suspense fallback={<View />}>
      <TouchableComponent {...props} />
    </Suspense>
  );
};

export default Touchable;

So anywhere on my app I want to use this component, I just have to do that:

import Touchable from './path/to/Touchable';

[...]
<Touchable>
  <Text>Touchable text</Text>
</Touchable>
[...]

Types.d.ts :

export type TouchableSizeType = 'small' | 'regular' | 'big';
export type TouchableType = 'primary' | 'secondary' | 'success' | 'error' | 'warning';

export interface TouchableProps {
  disabled?: boolean;
  size?: TouchableSizeType;
  type?: TouchableType;
  onClick?: (event?: Event) => Promise<void>;
}
like image 32
AnTSaSk Avatar answered Sep 29 '22 07:09

AnTSaSk