Using both React and React Native libraries in the same js file

353 views Asked by At

I'm writing a React + Redux + ReactNative Application, that shares the same code for multiple platforms (Web, IOS, Android).

So UI components are different, but the model and logic are shared between platforms.

I'm facing an issue when I'm trying to navigate to a different page, inside an action, example: (I'm using react-router and react-native-router-flux)

import {browserHistory} from "react-router";
import {Actions} from 'react-native-router-flux'; // This is the problematic import

export function signInSuccessAndRoute(user) {
    if (PlatformInfoShared.isWeb()) {
        const path = '/dashboard';
        browserHistory.push(path);
    } else {
        Actions.mainApplication();
    }
    return signInSuccess(user);
}

The problem is, on the Web I'm getting this error:

index.js:1Uncaught SyntaxError: Unexpected token import

I'm looking for a way to import as an If statement, meaning import only if the platform is Mobile/Web, how is that possible?

Or any another option you may think of... Thanks

2

There are 2 answers

0
MCMatan On BEST ANSWER

After trying to figure this problem out for some time, decided to document it here in case someone else will have the same issue.

The best way I've managed to deal with this is by creating a custom middle were, a different one for web and mobile, and then navigating by action payload.

Mobile middleware:

import {Actions} from 'react-native-router-flux';

const ActionableNavigationMobile = store => next => action => {

    if ( ! action.redirect ) return next(action);

    const functionName = action.redirect;

    Actions[functionName]();

    return next(action);

};

export default ActionableNavigationMobile;

Web middleware:

import {browserHistory} from "react-router";

const ActionableNavigation = store => next => action => {

    if ( ! action.redirect ) return next(action);

    const path = action.redirect;
    browserHistory.push(path);

    return next(action);
};

export default ActionableNavigation;

Add as middleware:

export const store = createStore(
    reducer,
    applyMiddleware(thunk,actionableNavigation), //Change this for web and modile stors..
);

Action:

export function signInSuccessAndRoute(user) {
    return dispatch => {
        const redirect = PlatformInfoShared.isWeb() ? "/dashboard" : "mainApplication";
        dispatch(signInSuccess(user));
        dispatch({redirect: redirect});
    };
}
1
Jeff Cousins On

Not sure if this will work because I haven't mixed React Native with React in the same application (and I'm not entirely sure how React Native will behave with these imports), but here's an idea that might work based off the concept of code splitting:

If you're using Webpack2, you can use ES2015's System.import to dynamically load your imports.

if (condition) {
  System.import('moduleName')
    .then(moduleName => {
      moduleName.methodName();
    });
}

If you're on Webpack1, require.ensure might do the trick.

if (condition) {
  require.ensure(['module-name', 'module-two'], () => {
    const ModuleName = require('module-name');
    const ModuleTwo = require('module-two');
    ModuleName.methodName();
  });
}

Notice the usage difference between the two. System.import returns a promise. Require.ensure's first argument is an array of module name(s), and its second argument is a callback where you may use the CommonJS require. Note that the callback does not need any parameters.

Best of luck!