CodePush is a magical service that lets you update your app on the fly! It means that when you find a bug in your app you can push the code instantly to your users and update their apps / release new features.
Why should I care?
With Native apps you have to go through app review process every time you release a new version. Sometimes its fast, sometimes its not. But with CodePush you can update JS part of the app bypassing the review!
npm install --save react-native-code-push
react-native link react-native-code-push
Wrap your top-level component in a codepush wrapper
import codePush from "react-native-code-push";
class TeamParrot extends Component {
...
}
export default codePush( TeamParrot );
Add deployment keys to your project
iOS: add to info.plist:
CodePushDeploymentKey
your key
To update and rollback your app:
code-push release-react TeamParrot-ios ios
code-push promote TeamParrot-ios Staging Production
code-push rollback TeamParrot-ios Production
Profit
React Native Isomorphic app over the weekend
This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.
You started building your app before you knew what it was, didn’t you? Well, that is certainly what I did.
My app started as “SlackBird”, then I realized that i may be violating some trademark there ( hint: probably not “bird” ), so I went and changed the name to “TLDR“. But after that I realized my addiction to Party Parrot so “TeamParrot” it is!
So what files should I actually change?
IOS
When you go to project details in Xcode, you can edit name. When you edit it, Xcode “Rename files” tool opens.
In ios/PROJECT/info.plist change CFBundleURLName
In ios/PROJECT.xcodeproj/xcshareddata/xcschemes/PROJECT.xcschemechangeBuildableName`
Rename file ios/PROJECT.xcodeproj/xcshareddata/xcschemes/PROJECT.xcscheme itself to NEWPROJECT.xcsccheme
Android
I just grepped for files containing my old name “TLDR” in this instance. These variables needed to be changed:
package in android/app/BUCK
applicationId in android/app/build.gradle
package in android/app/src/main/AndroidManifest.xml
return value of getMainComponentName in android/app/src/main/java/com/slackbird/MainActivity.java . That is the name of your main component in JavaScript portion.
package in android/app/src/main/java/com/PROJECT/MainApplication.java
Application name in android/app/src/main/res/values/strings.xml
React part
Now you renamed your min entry point to your application. So don’t forget to rename your main component name:
If you renamed everything, some directories will still have old name of your app. I decided I’m fine with that.
React Native Isomorphic app over the weekend
This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.
npm install react-native-vector-icons --save to install
How this works
This package provides fonts and some wrappers. Since SVG is still not working 100% on RN, introducing vector icons via font seems like a reasonable approach. In mobile apps you want to bundle the font with the app itself.
IOS
Theoretically, you should be able to rnpm link. Unfortunately, that didn’t work for me, so I had to install font manually:
Drag “Fonts” folder from node_modules/react-native-vector-icons to your project
You have to add fonts in info.plist This is how I added FontAwesome only:
UIAppFonts : Fonts/FontAwesome.ttf
ANDROID
In android/app/build.gradle
project.ext.vectoricons = [
iconFontNames: [ 'FontAwesome.ttf' ] // Name of the font files you want to copy
]
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
In android/settings.gradle :
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
Using
Now you want to plaster icons all over your application, don’t you? I do too!
If you are using Font Awesome like me, you would go to http://fontawesome.io/icons/ and pick your icon. You need the name without “fa-” at the beginning, and then you drop icon in your project like so:
import Icon from 'react-native-vector-icons/FontAwesome';
WEB
Because my project is isomorphic, this caused some problems in the web version. react-native-web is not yet compatible with react-native-vector-icons. To make the project even compile on the web, I made 3 files that abstracted the icon enough:
icon.web.js
import React from 'react';
import { Text } from 'react-native';
export default Text;
index.android.js and index.ios.js
import Icon from 'react-native-vector-icons/FontAwesome';
export default Icon;
Because isomorphism works in react native by picking specific files, my project now builds under all 3 environments. Granted, I would prefer it to build for web with working icons, which it does not do currently, but thats a battle for another day.
React Native Isomorphic app over the weekend
This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.
One of the most appealing qualities of React Native is the idea of isomorphic code. Code, that can run on both iOS and Android, enabling you to write 2 apps at the same time.
But, there is another benefit to isomorphic code. You can also speed up writing your code just for one app.
Since react Native is using React code, I initially wanted to develop parts of the application “the React way”, using hot reloading, React Devtools and the fast feedback cycle that web development permits. That would let me work on the app without emulators and building the code.
It’s possible and much more.
React-Native-Web
‘react-native-web’ builts your react native app as a web app. Not pieces and snippets, but the whole app. Granted, there is a lot of functionality missing, so it’s almost certain that you will have to modify your source a bit to even make the build work, but there is one use-case that it’s perfect for:
UI components.
In TeamParrot I have separated all UI components as “dumb components” without much logic nor dependencies. That way, I can develop UI separately from the whole app. I have made specific container-component for web that holds all of these dumb components and allows me to see all of them in one place, iterate and work on in my web browser.
Let’s do this!
If you want this also for your app, here is how I’ve done it for TeamParrot:
React-Native-Web-Starter
I used react native web boilerplate called react-native-web-starter to get started. I downloaded the latest master, dumped the files into root of TeamParrot project and… Build failed. Now web, ios, and android build stopped working.
Now, let’s fix it!
First need proper libraries in your package.json devDependencies:
You need to remove .babelrc provided by react-native-web-starter, since that will interfere with RN babel build process. But the configuration from .babelrc needs to end up somewhere, so you need to modify your package.json loader to include:
Everything seems ok at this moment, but the app still does not want to load. After debugging for a while it turned out that these components didnt want to play nice with React Native Web:
Switch used for toggles
Icon from `react-native-vector-icons`
RefreshControl used for “Pull to refresh” on iOS.
I decided on a n ugly solution that I would just render “Text” instead of Icon and not render Switch or RefreshControl at all by passing “webDevelopment” prop:
export default function MainView( { queue, playing, channels, stop, pause, play, refresh, loading, header, openDrawer, webDevelopment = false } ) {
const msg = get( queue, [ 0, 'items', 0 ] );
const scrollProps = { style: { flex: 4 } };
if ( ! webDevelopment ) {
//When building this component inside react-native-web, RefreshControl does not work correctly
scrollProps[ 'refreshControl' ] = ;
}
The last problem I needed to solve was loading images. React Native has a an Image component, to which you pass local images by require prop:
To make this work on web, with webpack, you need to install file-loader:
This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.
If you want to use any self-respecting API on the web, you are going to need Oauth authentication. If you need an explanation what oauth is, there are plenty better ones. These are the steps your app needs to go through:
Send user to special URL in the browser that lets them log in to the service
Handle callback URL from this service
Exchange keys with the service to make sure callback was legit
Store the token.
Since I used Slack API from the slack npm package, I had the “Exchanging the keys” parts ready.
0. Preparing the app
You thought we were going to start from 1, didn’t you? Well, you you must be new to this “programming” stuff. 😃 On the more serious note, you need to register your app in the API provider to get special keys for the step 1 and fill in URL for the step 2.
For TeamParrot, I set up following OAuth redirect URL:
1.Send a user to the special URL
You will need to use “Linking” library. DO NOT confuse Library called “Linking” with the process of “Linking libraries”, which is tying native libraries to JS code. I just send my users to 'https://slack.com/oauth/authorize?client_id=' + client_id + '&scope=channels:read%20channels:history%20users:read%20channels:write' and that opens web browser with appropriate “back” button.
2. Handling callback URL
If all goes good and your users give you appropriate permissions, they will be sent to the URL you specified in step 0. You may notice that this step has a weird protocol (team-parrot://). It actually can have any protocol you want that’s not used by an other app. This is enabled by “Deep linking” and “Intents” On android.
iOS
First, you need to configure your app to handle this specific link you want to capture. That tells the operating system to route those links to your beautiful and shiny app. As per usual, you have to do that in info.plist :
Deep linking is called “intents” in Android and much of the same concept applies. You have to tell the OS that you want to open certain protocol inside your app. So:
And now your function “handleUrl” will be responsible for confirming “CODE” and exchanging it for a token. Usually, that will be handled by your API library of choice. Here is how I did it for TeamParrot:
So there you have it. Now, you should be authenticated over Oauth2 with the slack API and able to make calls.
React Native Isomorphic app over the weekend
This article is part of my “React Native Isomorphic app over the weekend” series. It shares the problems I encountered during development of TeamParrot and Headstart Journal.
Oauth
Vector Icons – FontAwesome
CodePush
Renaming an App
Web & Isomorphic code development in Chrome devTools