James Adams
James Adams

Reputation: 748

Conditional imports in React Native

I'm having a bit of trouble getting conditional imports working in react native.

I have some files that are used in a react web app and in react native.

What I'd like:

if(process.env.REACT_PLATFORM === 'WEB') {
    import('some_file').then(({someFunc})=> someFunc())
}

Because 'some_file' imports react_router.

However, this import is still happening, and the RN metro bundler throws

UnableToResolveError: Unable to resolve module 'react-router' from 'some_file'.

Even If I replace it as:

if(false) {
    import('some_file').then(({someFunc})=> someFunc())
}

It still trys to load some_file. Is there anyway to only import/require this file if a condition is met?

Cheers!

EDIT: Things I've tried:

Upvotes: 25

Views: 20124

Answers (5)

Peter W
Peter W

Reputation: 1494

I came across a problem where the project I am working on is using react-native-tvos and I tried to add react-native-ad-manager as a dependency but it doesn't support tvOS so I wanted to dynamically import the ad manager dependency for non tvOS platforms. I was able to get it to work like such:

import {Platform} from 'react-native';

const NullComponent = (props: any) => null;

const AdComponent = () => {
  const [Banner, setBanner] = React.useState(() => NullComponent);

  if (!Platform.isTV) {
    import('react-native-ad-manager')
      .then(({Banner: AdBanner}) => {
        setBanner(() => AdBanner);
      })
  }

  return (
    <Banner />
  )
}

Upvotes: 3

x00
x00

Reputation: 13843

Platform specific imports are nice but won't help you on the web.

react-native section in package.json is your friend:

"react-native": {
  "module1": false,
  "module2": "module3"
}

with this setup

// module1
export const x = 1

// module2
export const x = 2

// module3
export const x = 3

// will result in
import {x} from 'module1'
console.log( x === undefined ) // in the react-native environment
console.log( x === 1 ) // in the browser

import {x} from 'module2'
console.log( x === 3 ) // in the react-native environment
console.log( x === 2 ) // in the browser

import {x} from 'module3'
console.log( x === 3 ) // in the react-native environment
console.log( x === 3 ) // in the browser

The docs can be found here. It's for the browser section, but the react-native section works the same way.

Upvotes: 4

Darshan
Darshan

Reputation: 2379

For React-navive-web we can use manage code for platform-specific that will manage in Mobile App and Web Also

Web-specific code # Minor platform differences can use the Platform module.

import { Platform } from 'react-native';

const styles = StyleSheet.create({
  height: (Platform.OS === 'web') ? 200 : 100,
});

For example, with the following files in your project:

MyComponent.android.js
MyComponent.ios.js
MyComponent.web.js
And the following import:

import MyComponent from './MyComponent'; React Native will automatically import the correct variant for each specific target platform.

Upvotes: 3

user5201343
user5201343

Reputation:

After a bit of searching, in turns out dynamic imports can be a bit of a pain.

This is the solution I came up with, I've tried it in node.

const MODULE_NAME = <CONDITION> ? require(MODULE_A) : require(MODULE_B);

Alternatively, I guess you could do something like this;

const MODULE_TO_IMPORT = 'MODULE_IMPORT_STRING';
const MODULE_NAME = import(MODULE_TO_IMPORT).then(({someFunc}) => someFunc());

But the problem is that these require a module to be imported either way.

Upvotes: 9

Shagymoe
Shagymoe

Reputation: 1456

Platform specific imports;

You can place the import in a component with the native.js extension and it will only be bundled for mobile (ios/android). e.g. MyComponent.native.js Then you have a component for web with the same name but the .js extension. e.g. My Component.js

When you import MyComponent from './components/MyComponent', the correct one will be imported and the other ignored.

Upvotes: 13

Related Questions