React Native and JUCE Tutorial

This tutorial is a walkthrough of how to get a JUCE project up and running with React Native. I am going to base my example on the React Native Navigation project which I have been using as the basis for React Native apps.

This tutorial assumes familiarity with JUCE, C++, modern Javascript (ES6) and a little Objective-C and Java. It also assumes that you already have a JUCE app that you wish to integrate with React Native.

There are two layers to how a C++ application can interact with React Native:

First we have to get to the “native” API for the platform: Objective-C on iOS, and Java on Android. Going from Objective-C to C++ is fairly trivial as we can use Objective-C++, going back is a little more complicated. Going from Java to C++ is a little convoluted, having to go via the cryptic puzzle that is JNI, and going from C++ to Java is a little more complicated still. But its all doable once you get the basics going!

Secondly we have the native to Javascript bridge, for which there are examples at the React Native docs. Basically we have to define some special methods that can then be called from Javascript, and/or allow native methods to call Javascript methods.

iOS — Setting up

The following assumes you have a standard JUCE app with a default (or close to) Main.cpp file.

Inside your Main.cpp you will find a MainWindow class. We will be creating a new MainWindow class, calling it MainWindowIOS, which will define an Objective-C++ class that will start up our React Native app, and allow us to show a JUCE Component as a UIView.

Add the following two files, ideally from the Projucer so they are added to the XCode project as well as your .jucer file. I keep all my iOS only source files in a separate subfolder, i.e. Source/iOS.

MainWindowIOS.h

MainWindowIOS.mm

Next we need to modify our Main.cpp to use our new class. Remove the MainWindow class defined within Main.cpp and copy it into a seperate file (e.g. MainWindow.h) in case you need it for a desktop version of your app.

Your Main.cpp should now look something like this:

Thats our initial code modifications done. Next we need to set up our node packages, import React Native and (if you choose to use it) the React Native Navigation library. This is done via CocoaPods. For a detailed walk-through please refer to the React Native Getting Started Guide linked below.

Tip: you might want to install yarn first and use it in place of npm.

And then here. Make sure you create your Podfile in Builds/iOS. See ya in a bit.

Ok, so now you should have anode_modules folder within your project folder, a package.json file, and a Podfile. (The Podfile is written in Ruby in case you were wondering). You need to make a small change to adapt to how JUCE now names the Xcode target:

target 'MyApp' do

Becomes

target 'MyApp (App)' do

Create folder ReactNative at the top level of your project. This is where your Javascript files will live.

Also (for compatibility with RNN at the time of writing), make sure you have version 0.31 of React Native in your package.json, which should look like this:

{
"name": "MyApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start --root ./ReactNative"
},
"dependencies": {
"react": "15.2.1",
"react-native": "0.31.0"
}
}
cd Builds/iOS
pod init

Now open up the generated Podfile and add the following, adapted to your project:

Add the React Native Navigation library

If you want to use the React Native Navigation library we need to install it via npm and then add it to our Podfile.

npm install react-native-navigation@next --save

Now open up Builds/iOS/Podfile in your editor and add RNN to it. Within your target block add:

pod 'ReactNativeNavigation', :path => '../../node_modules/react-native-navigation'

Now we need to generate a Podspec for RNN.

npm install -g podspec-generator
podspec-generator ../../node_modules/react-native-navigation

Now we need to open up Projucer and add the following line, to Preprocessor definitions, both for debug and release builds:

$(inherited)

We also need to change the Binary Location setting for both iOS builds to:

$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

While we are in Projucer, we also need to add a custom PList entry to allow React Native to communicate with the node server in debug mode. Add the following to the Custom PList field:

<plist>
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>codegarden.cloudant.com</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</plist>

Now you can go ahead and open your workspace in Xcode. Make sure it builds (Cmd+B). We’re not ready to run it just yet.

Adding a Custom View

We need some boilerplate code in order to make React Native aware of our JUCE Component.

Next we’re going to set up our Android environment for React Native in Part 2. If you want to skip to the next step for iOS you can go to Part 3.

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store