kanzitelli / rnn-starter

🤹 React Native Starter - Powered by cli-rn, React Native Navigation, Expo Modules, RNN Screens, RN UI lib, MMKV, Mobx, Reanimated 2, Dark Mode, Splash Screen, Localization, Notifications, Permissions, and much more.
https://starters.dev
MIT License
550 stars 72 forks source link

help needed: Convert uni-modules to expo-modules #57

Closed julianklumpers closed 2 years ago

julianklumpers commented 2 years ago

Looks like Expo has deprecated uni-modules: https://docs.expo.dev/bare/installing-unimodules/ And switched to expo-modules: https://blog.expo.dev/whats-new-in-expo-modules-infrastructure-7a7cdda81ebc

Now I was trying to get it to work for Android with react-native-navigation and i was able to migrate the code to get the app to compile successfully, but with no luck, the navigation is not working. I think the part where it gets stuck is in MainActivity.java

https://docs.expo.dev/bare/installing-expo-modules/#configuration-for-android

As you can see, the code inside public class MainActivity extends NavigationActivity is not working and if I omit the code the app is compiled successfully, but the navigation is not working.

The following code is not working

package com.myApp;

import com.reactnativenavigation.NavigationActivity;

import com.facebook.react.ReactActivityDelegate;
import expo.modules.ReactActivityDelegateWrapper;

public class MainActivity extends NavigationActivity {
  @Override
  protected String getMainComponentName() {
    return "MyApp";
  }

  @Override
  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegateWrapper(this,
      new ReactActivityDelegate(this, getMainComponentName())
    );
  }
}

Some help would be appreciated.

kanzitelli commented 2 years ago

Hey @julianklumpers! I am not sure if I understood it correctly, but rnn-starter doesn't have deps on uni(expo)-modules. Or do you mean that you use them in your project and have some problems with configuring?

julianklumpers commented 2 years ago

Hi @kanzitelli,

I was using this repo for our project together with expo uni-modules. uni-modules lets you use expo libs in a bare react-native project.

Also i think its a great addition to this repo to be able to use expo modules and would like some help to get it working with react-native-navigation.

Also the tags implied this repo is using uni-module Screenshot 2021-10-27 at 17 14 09

kanzitelli commented 2 years ago

Oh cool, because a year ago I was supporting uni-modules for this starter but decided that it's better to go fully bare with RNN. But I will create a branch with a playground for expo-modules. And will keep this issue just for the progress :)

julianklumpers commented 2 years ago

Cool, I'm happy to help

julianklumpers commented 2 years ago

I got it working for Android.

In MainActivity.java leave it as it is

package com.myApp;

import com.reactnativenavigation.NavigationActivity;

public class MainActivity extends NavigationActivity {}

The key to get it working is in MainApplication.java In the expo docs they explain you have to add new ReactNativeHostWrapper just skip this part and add the rest of the changes in https://github.com/expo/fyi/blob/master/expo-modules-migration.md and everything works fine! you can now use the new expo-modules.

package com.myApp;

import com.airbnb.android.react.lottie.LottiePackage;

import android.content.Context;
import android.content.res.Configuration;
import androidx.annotation.NonNull;
import com.facebook.react.PackageList;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.bridge.JSIModulePackage;
import com.reactnativenavigation.NavigationApplication;
import com.reactnativenavigation.react.NavigationReactNativeHost;
import com.facebook.react.ReactPackage;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

import expo.modules.ApplicationLifecycleDispatcher;
import com.reactnativemmkv.MmkvModulePackage;

public class MainApplication extends NavigationApplication {

  private final ReactNativeHost mReactNativeHost = new NavigationReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // Packages that cannot be autolinked yet can be added manually here, for example:
          // packages.add(new RNVersionCheckPackage());
          packages.add(new LottiePackage());

          return packages;
        }

        @Override
        protected String getJSMainModuleName() {
          return "index";
        }

        @Override
        protected JSIModulePackage getJSIModulePackage() {
          return new MmkvModulePackage();
        }
      };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
    ApplicationLifecycleDispatcher.onApplicationCreate(this);
  }

  @Override
  public void onConfigurationChanged(@NonNull Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
  }

  /**
   * Loads Flipper in React Native templates. Call this in the onCreate method with something like
   * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
   *
   * @param context
   * @param reactInstanceManager
   */
  private static void initializeFlipper(
      Context context, ReactInstanceManager reactInstanceManager) {
    if (BuildConfig.DEBUG) {
      try {
        /*
         We use reflection here to pick up the class that initializes Flipper,
        since Flipper library is not available in release mode
        */
        Class<?> aClass = Class.forName("com.natutecscout.ReactNativeFlipper");
        aClass
            .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
            .invoke(null, context, reactInstanceManager);
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      } catch (NoSuchMethodException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
    }
  }
}

Hope this helps for others that are using rnn-starter and want to use expo-modules.

kanzitelli commented 2 years ago

Hey @julianklumpers! That looks great, thanks! Did you manage to run it on iOS? Because I didn't try it yet, I have been busy with writing a small library for RNN called rnn-screens, and I am celebrating my bday today, so I will be probably back at the beginning of the next week, and let's integrate it to rnn-starter!

julianklumpers commented 2 years ago

@kanzitelli

Congratulations! with your birthday, hope you had a good day. For IOS i'm working on it as we speak. Will let you know when i have something. nice that we can intergrate it.

kanzitelli commented 2 years ago

Hey @julianklumpers! Thank you so much for congrats 🙏 so yeah, the celebration was good and gave me the motivation to work more! So hopefully, I will spend more time on this issue and could help you as well.

kanzitelli commented 2 years ago

Hey @julianklumpers! I have created expo-modules branch where Expo Modules are integrated and the app runs on iOS and Android successfully. If everything works out good, I will add it in the documentation.

julianklumpers commented 2 years ago

Hi @kanzitelli. Great to hear it working and will be integrated into this package. Sorry for not responding anymore, was very busy with work.

kanzitelli commented 2 years ago

Hey @julianklumpers! That's all right, thank you for the opening this issue and helping out! I will close this for now and add the branch into docs.

SudoPlz commented 8 months ago

@kanzitelli @julianklumpers it seems like you hooked up the expo lifecycle events, but you're not actually using the expo.modules.ReactNativeHostWrapper anywhere (still using the react-native-navigation host)

Is that intentional? It feels that this (will build but) would actually break expo functionality. Any idea what would break in expo by doing that, I wonder if I can omit it too in my implementation?