Updating ReactNativeExpo.js v1 to v2
Tags: reactnative, expo, nativebase
Published: 2020-04-20 16:20:24

Sadly, version 1 of the [ReactNativeExpo.js](https://github.com/migu33l/ReactNativeExpo.js) has gone to the end because of continuous breaking changes of Expo and React Native, but don't be alarm yet, this is not a bad thing, is just version 1 is no more supported.

Never the less, we are making some changes to the project to fulfill all the need for the continuous function of the project, let's call it version 2 now.

Note aside; this guide is for migrating from version 1 to version 2. If you want to start from fresh from version 2, follow the instruction on the repository.

If you are still here, let's continue:

## Version 1 to version 2

I split the migration into three parts; files that need delete, create, and must make some changes. Let's go:

### Files to Delete

- **package-lock.json**
- **.babelrc**
- **docs**
- **src/assets/native-base-theme**:

Because of the update of Native-Base, for working correctly, we must delete de folder src/assets/native-base-theme and copy the new one.
```
    rm -rf ./src/assets/native-base-theme
    node node_modules/native-base/ejectTheme.js
    mv ./native-base-theme ./src/assets/native-base-theme
```
### File to Create

- **index.js**
```javascript
    import { registerRootComponent } from 'expo';
    
    import App from './App';
    
    // registerRootComponent calls AppRegistry.registerComponent('main', () => App);
    // It also ensures that whether you load the app in the Expo client or in a native build,
    // the environment is set up appropriately
    registerRootComponent(App);
```
- **.buckconfig**
```
    [android]
      target = Google Inc.:Google APIs:23
    
    [maven_repositories]
      central = https://repo1.maven.org/maven2
```
- **babel.config.json**

Handle the responsibility that one day has .babelrc
```javascript
    module.exports = function (api) {
      api.cache(true);
      return {
        presets: ['babel-preset-expo'],
        plugins: [
          [
            'module-resolver',
            {
              root: ['./'],
              alias: {
                '@app': './src/app',
                '@assets': './src/assets',
                '@common': './src/common',
                '@components': './src/components',
                '@constants': './src/constants',
              },
            },
          ],
        ],
      };
    };
```
- **.gitattributes**
```
    *.pbxproj -text
```
- **.prettierignore**
```
    package.json
    package-lock.json
    .vscode/*
```
- **.prettierrc**
```
    {
      "bracketSpacing": true,
      "semi": true,
      "singleQuote": true,
      "trailingComma": "es5",
      "printWidth": 80,
      "tabWidth": 2
    }
```

### File to replace

- **package.json**

With all dependencies updated.
```
    {
      "name": "react-native-expo-starter",
      "homepage": "https://github.com/migu33l/React-Native-Expo-Starter",
      "version": "2.0.0",
      "devDependencies": {
        "@babel/core": "^7.9.0",
        "eslint": "^6.8.0",
        "eslint-config-airbnb-base": "^14.1.0",
        "eslint-config-prettier": "^6.10.1",
        "eslint-import-resolver-babel-module": "^5.1.2",
        "eslint-plugin-flowtype": "^4.7.0",
        "eslint-plugin-import": "^2.20.2",
        "eslint-plugin-prettier": "^3.1.3",
        "eslint-plugin-react": "^7.19.0",
        "eslint-plugin-standard": "^4.0.1",
        "prettier": "^2.0.4",
        "redux-logger": "^3.0.6",
        "schedule": "^0.5.0"
      },
      "main": "index.js",
      "scripts": {
        "android": "react-native run-android",
        "ios": "react-native run-ios",
        "web": "expo start --web",
        "start": "expo start",
        "test": "jest"
      },
      "dependencies": {
        "@expo/vector-icons": "^10.0.6",
        "@react-native-community/async-storage": "^1.9.0",
        "axios": "^0.19.2",
        "babel": "^6.23.0",
        "babel-eslint": "^10.1.0",
        "babel-plugin-module-resolver": "^4.0.0",
        "expo": "~37.0.3",
        "expo-splash-screen": "^0.1.1",
        "expo-updates": "~0.1.0",
        "native-base": "2.13.8",
        "prop-types": "^15.7.2",
        "react": "~16.9.0",
        "react-dom": "~16.9.0",
        "react-native": "~0.61.5",
        "react-native-gesture-handler": "~1.6.0",
        "react-native-reanimated": "~1.7.0",
        "react-native-screens": "~2.2.0",
        "react-native-unimodules": "~0.9.0",
        "react-native-web": "~0.11.7",
        "react-redux": "^7.2.0",
        "redux": "^4.0.5",
        "redux-persist": "^6.0.0",
        "redux-thunk": "^2.3.0"
      },
      "private": true
    }
```
- **packager-info.json**
```
    {
      "devToolsPort": 19002,
      "expoServerPort": null,
      "packagerPort": null,
      "packagerPid": null,
      "expoServerNgrokUrl": null,
      "packagerNgrokUrl": null,
      "ngrokPid": null,
      "webpackServerPort": null
    }
```
- **settings.json**
```
    {
      "hostType": "lan",
      "lanType": "ip",
      "dev": true,
      "minify": false,
      "urlRandomness": "xe-t27",
      "https": false
    }
```
- **src/app/store.js**

In the last version of redux-persist@~6 the storage is not compatible and brings us an exception (AsyncStorage exception). You got two options:

- Use redux-persions@~5, and no code must be changed.
- Use redux-persist@~6, and must do these changes to store.js file.
```javascript
    // before
    ...
    import storage from "redux-persist/es/storage";
    ...
    
    // after
    ...
    import { AsyncStorage } from "react-native";
    ...

    // before
    ...
    const config = {
      key: "root",
      storage,
      blacklist: ["status"]
    };
    ...
    
    // after
    ...
    const config = {
      key: "root",
      storage: AsyncStorage,
      blacklist: ["status"]
    };
    ...
```
- **src/assets/fonts/Questrial-Regular.ttf**

Changed his name for Questrial.ttf

- **.gitignore**
```
    # OSX
    #
    .DS_Store
    
    # Xcode
    #
    build/
    *.pbxuser
    !default.pbxuser
    *.mode1v3
    !default.mode1v3
    *.mode2v3
    !default.mode2v3
    *.perspectivev3
    !default.perspectivev3
    xcuserdata
    *.xccheckout
    *.moved-aside
    DerivedData
    *.hmap
    *.ipa
    *.xcuserstate
    project.xcworkspace
    
    # Android/IntelliJ
    #
    build/
    .idea
    .gradle
    local.properties
    *.iml
    
    # node.js
    #
    node_modules/
    npm-debug.log
    yarn-error.log
    
    # BUCK
    buck-out/
    \.buckd/
    *.keystore
    
    # fastlane
    #
    # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
    # screenshots whenever they are needed.
    # For more information about the recommended setup visit:
    # https://docs.fastlane.tools/best-practices/source-control/
    
    */fastlane/report.xml
    */fastlane/Preview.html
    */fastlane/screenshots
    
    # Bundle artifacts
    *.jsbundle
    
    # CocoaPods
    /ios/Pods/
    
    # Expo
    .expo/*
    /web-build
```
- **App.js**
```javascript
    import * as React from 'react';
    import { AppLoading } from 'expo';
    import * as Font from 'expo-font';
    import { Ionicons } from '@expo/vector-icons';
    
    import { Provider } from 'react-redux';
    import { PersistGate } from 'redux-persist/es/integration/react';
    import { StyleProvider } from 'native-base';
    import { StatusBar, Platform } from 'react-native';
    
    import getTheme from '@assets/native-base-theme/components';
    import theme from '@assets/native-base-theme/variables/commonColor';
    
    import configureStore from '@app/store';
    import Loading from '@components/loading/Loading';
    import Dashboard from '@components/dashboard/Dashboard';
    
    const { persistor, store } = configureStore();
    
    if (Platform.OS === 'android') StatusBar.setHidden(true);
    
    export default class App extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          isReady: false,
        };
      }
    
      async componentDidMount() {
        await this.loadFonts();
      }
    
      async loadFonts() {
        await Font.loadAsync({
          Roboto: require('native-base/Fonts/Roboto.ttf'),
          Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
          Questrial: require('@assets/fonts/Questrial.ttf'),
          ...Ionicons.font,
        });
    
        this.setState({ isReady: true });
      }
    
      render() {
        if (!this.state.isReady) {
          return <AppLoading></AppLoading>;
        }
    
        return (
          <Provider store={store}>
            <PersistGate loading={<Loading />} persistor={persistor}>
              <StyleProvider style={getTheme(theme)}>
                <Dashboard />
              </StyleProvider>
            </PersistGate>
          </Provider>
        );
      }
    }
```
- **app.json**
```
    {
      "name": "React Native Expo Starter",
      "displayName": "ReactNativeExpoStarter",
      "expo": {
        "name": "React Native Expo Starter",
        "slug": "React-Native-Expo-Starter",
        "icon": "src/assets/images/app-icon.png",
        "version": "2.0.0",
        "orientation": "portrait",
        "platforms": ["ios", "android", "web"],
        "assetBundlePatterns": ["**/*"]
      }
    }
```
## Final Step

So we're done, let execute these commands:
```
    # remove dependencies
    rm -rf node_modules

    # for clean npm cache
    npm cache clean --force
    
    # install dependencies
    npm i
    
    # expo start
    npm start
```
And that its, everything must do ok.

If you had any doubt, don't hesitate and contact me, or better, contribute to this project, making changes and PR.

## Extra

Version 2 of this project has disabled react-native by default (for the moment) because it has some problems with ScreenSplash.

In the meantime, if you want to fix these problems, this must-do first:3 install.
```
    # install the expo client
    npm install --global expo-cli
    
    # create a new project
    expo init my-project
    
    # copy the folder from my-project/ios and my-project/android and paste in the root of the project
    
    # if you want to test ios, first must install CocoaPods and execute this command
    pod install
    
    # modify the package.json and add this 2 lines underline scripts
    		"android": "react-native run-android",
        "ios": "react-native run-ios",
    
    # now you can run ios and android nativly
    npm run ios
    npm run android
```