How to integrate ReactJS web code with a new React Native project?

I have web application code which is written using react js framework. Now our client wants to create mobile application using hybrid apps concept. So Is it possible to convert or reuse the web code which is written on react js to react native??

I have web application code which is written using react js framework. Now our client wants to create mobile application using hybrid apps concept. So Is it possible to convert or reuse the web code which is written on react js to react native??

Can anyone please suggest with any coding/project examples.

Thanks in advance.

React Native vs. Ionic: Which one is right for you?

React Native vs. Ionic: Which one is right for you?

In this article, I am going to compare two popular mobile frameworks, React Native and Ionic. We will first see how they are similar and also explore their differences. This guide can help you decide which framework is right for you.

Originally published by Adhithi Ravichandran at https://blog.logrocket.com

Mobile development does not mean just native iOS development using Swift or native Android development using Java anymore. We are in the generation of hybrid, cross-platform and progressive web apps.

React Native basics

React Native is a cross-platform solution to build mobile apps natively on both iOS and Android. It is coded in JavaScript using React. It was open-sourced back in 2015 by Facebook and has gained immense popularity ever since.

React Native is used to build native mobile apps using JavaScript and React on both iOS and Android.

Ionic basics

Ionic is a hybrid solution to build your mobile apps. It allows you to use standard web technologies like JavaScript, HTML, and CSS to build high-quality, cross-platform apps. Ionic Framework has released a free eBook that explains the differences between a hybrid app vs. a native app.

The idea is that you code once, and that code can be deployed cross-platform on iOS, Android, Web, and desktop. The same code-base is shared across all the platforms.

How are they similar?

If you are just learning about both React Native and Ionic, they probably sound very similar from the description above.

Ionic lets you build mobile, desktop and web apps using traditional web technologies like JavaScript/CSS/HTML. Similarly, React Native lets you build native mobile apps using JavaScript and the popular JavaScript framework, React.

This means you don’t need to know native iOS or Android development to use Ionic or React Native.

How are they different?

Now let’s learn how these frameworks are different.

1. Native vs. hybrid

React Native is native

React Native is used to build truly native cross-platform apps. A native app is a software application built in a specific programming language, for the specific device platform, either iOS or Android.

Native iOS apps are written in Swift or Objective-C and native Android apps are written in Java. With React Native the underlying widgets are all native components, giving the user a seamless experience. It is built using JavaScript and React but the components are all native components of iOS and Android. The beauty of React Native, is that it builds native apps, on both iOS and Android, with a single code base.

It is really impressive since you are coding in Javascript, and rendering components that are native to the platform. This is one of the reasons that apps built using React Native have a superior user experience in comparison to frameworks that use Web Views.

Ionic is hybrid

Ionic is a hybrid app. It uses HTML, CSS, and JavaScript to build apps that can be used on web, desktop, and mobile. Hybrid apps essentially use what is called a Web View to build mobile apps.

Ionic apps are built using web technologies and are rendered using Web Views. Ionic apps are built using web technologies and are rendered using Web Views, which are a full screen and full-powered web browser.

The idea here is to reuse code across multiple platforms. So hybrid apps will not have access to native features of the mobile device out of the box. Native features like camera, GPS, contacts and so on. Ionic uses Cordova plugins to integrate native features to your app. Ionic renders its graphic elements via a browser, which takes several steps to start showing the component on the screen. This could cause a performance hit on larger apps.

But when you are building web applications, using hybrid technologies like Ionic, it is easy to convert them to Progressive Web Apps that can be downloaded just like any other mobile app.

Winner: React Native

If your product is solely a mobile app that needs to work cross-platform on iOS and Android and needs to look and feel like a native app, you should pick React Native. If you are looking for an elegant user interface that matches your website in the form of a mobile app, you could consider Ionic instead.

2. Technology stack

React Native

React Native is written in JavaScript using the popular framework React. The UI pieces are written in JSX, instead of HTML. JSX looks like any other template language but comes with all of the powers of JavaScript. The reason React Native uses React is because both the frameworks were developed and open-sourced by Facebook and it makes sense that they chose React to build React Native.

Ionic

You could use Angular, Vue, or even React to build Ionic apps. Ionic’s tech stack is a lot more flexible compared to React Native. With the latest release of Ionic 4, you can use Ionic with any web development framework.

Winner: Ionic

Until last year, React Native could have been considered a winner in this category because Ionic apps were built using only Angular. But with the recent updates to Ionic, it opens up a huge amount of flexibility in building Ionic apps. Any web developer, on any modern web framework, can develop Ionic apps. This is a huge perk for Ionic, making it a winner in this category.

3. Popularity

Before beginning your quest to learn React Native or Ionic, let’s look at which one is more popular.

To get more insight into their popularity factors, let’s take a look at the State of JavaScript survey of 2018. It released data on both React Native and Ionic popularity over the last three years among developers.

From this survey results below, we can infer that React Native is definitely more popular as a mobile framework when compared to Ionic.

Winner: React Native

React Native’s greater popularity is due to its ability to build truly “native” apps using JavaScript and React. The concept of a hybrid app using WebViews is good, but it does not come close to the look and feel of a native app. Ionic being a hybrid app lacks the looks and feel of a truly native app. Whereas, React Native apps are native and it is awesome that the components are all native to iOS and Android. The end-user will not be able to distinguish between a native app and a React Native app. This is the most important factor contributing to React Native’s popularity.

4. Learning curve

React Native

If you are a React developer, then learning React Native is extremely easy. The concepts are the same, and you code in React. The only difference is that React uses web components like <div>, <p>, whereas React Native uses components that are wrappers around native iOS and Android components like <View>. It shouldn’t take a long time for a React developer to become a React Native developer.

That being said, what about newbies who don’t know React? Learning React Native means, you have to learn JavaScript and React. You also need to start thinking like a mobile developer, since you are going to build mobile apps and not web apps. The learning curve could be considered steep for someone with no React knowledge.

Ionic

We already saw that Ionic’s tech stack is flexible. You are going to use JavaScript, CSS, and HTML along with your choice of web framework. It could be Angular, React, Knockout, Vue or any other modern web framework. This means developers who adopt Ionic framework, are going to pick the framework that they are already comfortable in to develop apps. Hence, the learning curve here is not as much as React Native.

With Ionic, you are essentially building web apps, that can become mobile apps. This hybrid approach is different in comparison to React Native’s native approach. This is easier for developers to grasp.

Winner: Ionic

Ionic has less of a learning curve in comparison to React Native. This is because Ionic allows you to pick a framework of your choice that you are comfortable in. It could be Angular, React, Vue or even plain JavaScript. Whereas with React Native, you have to code in React, and there is no flexibility with the tech stack. For a non-React developer, the learning curve is higher with React Native.

5. Performance

If you truly want the best performance, your best bet is to code native apps separately on iOS and Android. This is because native coding provides access to native features directly when you code. There is no layer of abstraction, and the direct interaction with native iOS and Android modules leads to enhanced performance. Both React Native and Ionic cannot match the native performance. Nevertheless, let’s look at which one is better.

React Native

React Native is closer to native performance than Ionic. React Native is essentially building native apps, using JavaScript. It has the look and feel of a native app and uses the same building blocks that native apps use. The only difference is that it is cross-platform and uses JavaScript to wrap around these native building blocks. React Native provides great performance and responsiveness to your mobile apps.

Ionic

Ionic on the other hand is a hybrid approach. It does not build native apps, and you could encounter performance issues. There are a lot of callbacks to the native code, which could cause lag. Ionic also requires the Cordova plugin, in case you need to access native features. Although Ionic is a great solution for building elegant UI and faster development, it does come with some performance issues when compared with frameworks like React Native.

Winner: React Native

React Native provides better performance than Ionic. The additional layer in Ionic, which involves Cordova plugins adds to the slowness since it is building a WebView and not a native app. React Native, on the other hand, wraps around native components, hence providing better performance.

6. Developer community

While evaluating a technology for your team, it is a good idea to explore the community involvement for that technology.

Let’s take a look at how React Native and Ionic compare with respect to the developer community and open-source contributions.

The GitHub stats is a good indication of community involvement for both the frameworks. React Native has about 78k stars with over 1900 contributors to the framework. This indicates that it is hugely popular in the community.

Ionic on the other hand has about 38k stars with only around 330 contributors to the framework. This is less than one-fifth the contributors when compared with React Native.

Winner: React Native

React Native has a much more active and engaged developer community when compared to Ionic. This could be owing to the reason that, it does build native mobile apps and not web apps. And also the fact that it uses React to build them.

Summary

Pros of React Native

Cons of React Native

  • React Native is not suitable if you are trying to build an app which is extremely heavy on animations, like a gaming app
  • Developers have to learn React before they begin React Native

Pros of Ionic

  • Written in JavaScript the supports most modern frameworks like React, Angular and Vue
  • Flexible for developers to pick a framework
  • Builds cross-platform hybrid apps on both iOS and Android

Cons of Ionic

  • Does not perform as well as cross-platform native apps or native apps
  • Have to use Cordova plugins, to use native APIs and modules
  • Builds a Web View, which will not translate to the look and feel of a native app
Conclusion

So who won? In this post, React Native is the winner. Of course, there is never the “right” framework. If you are planning on building cross-platform apps, make sure you evaluate your use-cases and developer preferences to decide which framework to pick.

Both React Native and Ionic come with their own pros and cons, and it takes careful evaluation to pick one or the other for your development.

Post your comments below and let us know what you decide and why?

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

Which one is best for you? Flutter, React Native, Ionic or NativeScript?

Ionic Framework 4 - Full Course - iOS / Android App Development

Building CRUD Mobile App using Ionic 4, Angular 8

Which one is best for you? Flutter, React Native, Ionic or NativeScript?


Fun, Fast, and Free Login with React Native

Fun, Fast, and Free Login with React Native

React Native is a mobile app development framework that allows you to use React to build native iOS and Android mobile apps. Instead of using a web view and rendering HTML and JavaScript, it converts React components to native platform components....

React Native is a mobile app development framework that allows you to use React to build native iOS and Android mobile apps. Instead of using a web view and rendering HTML and JavaScript, it converts React components to native platform components. This means you can use React Native in your existing Android and iOS projects, or you can create a whole new app from scratch.

In this post, I'll show you how to add a login feature to a React Native application using OAuth 2.0 and OpenID Connect. Authentication and authorization are important parts of most applications as you often need to know who a user is (authentication) and what they're allowed to do (authorization). OAuth 2.0 is an industry-standard protocol for authorization and OpenID Connect (OIDC) is an authentication layer on top of OAuth 2.0. Integrating with an always-on service like Okta for OAuth makes set up and configuration easy, particularly with React Native and Okta's React Native SDK.

React Native 0.61 was just released a couple of weeks ago. One of its biggest features is Fast Refresh - a unification of live reloading (reload on save) and hot reloading. Fast Refreshfully supports modern React's functional components and hooks and recovers after typos and other mistakes. In previous versions of React Native, a common complaint was that "hot reloading" was broken.

Prerequisites:

  • Node 10
  • Yarn
  • Watchman
  • Java 8 (for Android)
  • An Okta Developer Account

To install these prerequisites on a Mac, Linux, or Windows Subsystem for Linux (WSL), I recommend using Homebrew.

brew install node
brew install yarn
brew install watchman
brew tap AdoptOpenJDK/openjdk
brew cask install adoptopenjdk8

If you're not using WSL for Windows, you can use Chocolatey to install everything from the command line:

choco install -y nodejs.install python2 jdk8

You'll also need to download and install IDEs for Android and iOS:

You can sign up for an Okta developer account at developer.okta.com/signup.

Essential Reading: Learn React from Scratch! (2019 Edition)

Create a React Native Application

React Native CLI is a popular way to get started with React Native development.

npm install -g [email protected]

Once you have React Native CLI installed, you can create a new application using the init command.

react-native init ReactNativeLogin
Add Login with OIDC

Okta provides a React Native SDK which conveniently wraps the Okta native Android OIDC and iOS OIDC libraries.

I’m going to show you two ways to add OIDC-based login with Okta: The fast way with a tool I created and the step-by-step instructions.

This tool is based on Schematics and manipulates your project to install and configure everything.

Install Schematics globally.

npm install -g @angular-devkit/[email protected]
Create a Native App in Okta

Log in to your Okta Developer account (or sign up if you don't have an account).

  • From the Applications page, choose Add Application.
  • On the Create New Application page, select Native as the platform and click Next.
  • Give your app a memorable name, select Refresh Token as a grant type, and click Done.
  • Click the Edit button and add a Logout redirect URI that matches the default Login redirect URI (e.g., com.okta.dev-123456:/callback).
  • Click Save.
Install React Native OIDC Login

In a terminal, navigate into your ReactNativeLogin directory and install OktaDev Schematics:

npm i @oktadev/[email protected]

NOTE: If you have a React Native 0.60.x app, use @oktadev/[email protected]. The only difference between the two is the tests.

Run the add-auth schematic in your ReactNativeLogin project.

schematics @oktadev/schematics:add-auth

You will be prompted for an issuer and a clientId. You can find your issuer under API > Authorization Servers on Okta.

The client ID will be on your application screen.

This process will take a minute to complete.

Configure Your iOS Project to use Swift

React Native uses Objective-C, but the Okta React Native library uses Swift. Because of this, you have to add a Swift file in your iOS project for it to compile. Run the following command to open your native iOS project in Xcode.

open ios/ReactNativeLogin.xcworkspace

To add a Swift file, complete the following steps:

  1. Right-click on your project and select New File....
  2. Select Swift File, and click Next.
  3. Enter a name (e.g., Polyfill) and click Create.
  4. If prompted for a header file, it is not required to create one.

Then cd into ReactNativeLogin/ios and run pod install.

TIP: If you don't have CocoaPoads installed, you can install it with gem install cocoapods.

Run Your React Native App on iOS

Navigate back to the root directory of your app. Start your app and you should be able to authenticate with Okta. 🎉

react-native run-ios

Once you're signed in, you'll see options to log out, get the user's information from an ID token, and get the user's information from the React Native SDK's getUser() method (a.k.a. the request).

NOTE: The prompt when you click Login cannot be avoided. This is an iOS safety mechanism. It also pops up when you log out. See this issue for more information.

Run Your React Native App on Android

The schematic you ran modifies all the necessary files for Android; there are no code modifications required!

You will need to run an AVD (Android Virtual Device) before starting your app, or you can plug in your Android phone and use that. If you have neither, launch Android Studio and go to Tools > AVD Manager. Click Create Virtual Device at the bottom and select a phone of your choice. I chose a Pixel 3 XL with Android 10.

Start your AVD, then your app, and authenticate with Okta. 🎊

react-native run-android

Click the Get User from ID Token button to confirm you can retrieve the user's information.

Run Installed React Native Authentication Tests

In addition to integrating login, OktaDev Schematics also installed some tests that verify login and authentication work. Run npm test to see these tests run in your terminal.

Snapshot Summary
› 1 snapshot written from 1 test suite.

Test Suites: 2 passed, 2 total
Tests:       12 passed, 12 total
Snapshots:   1 written, 1 total
Time:        8.952s
Ran all test suites.

NOTE: OktaDev Schematics puts tests in a tests directory rather than the default __tests__ directory because Angular Schematics uses double underscore as a placeholder.

Using a Custom Login Screen with Okta

This example showed you how to add an OIDC flow that opens a browser when a user logs in and logs out. If you require a smoother login experience that doesn't pop open a browser, see Okta's Custom Sign-In Example for example code that shows you how to implement that type of flow.

Add OIDC Login the Hard Way

The previous section showed you how to use OktaDev Schematics to quickly add a login feature (and tests!) to a React Native application. However, you might have an existing React Native application that doesn't have the same structure as a brand new React Native application.

This section shows you everything that OktaDev Schematics does for you, in detail.

Create a project with React Native CLI and install Okta's SDK.

react-native init ReactNativeLogin
cd ReactNativeLogin
npm install @okta/[email protected]

For iOS, modify ios/Podfile to change it from iOS 9 to iOS 11.

platform :ios, '11.0'

Open your project in Xcode.

open ios/ReactNativeLogin.xcworkspace

Add a Swift file.

  1. Right-click on your project and select New File....
  2. Select Swift File, and click Next.
  3. Enter a name (e.g., Polyfill) and click Create.
  4. If prompted for a header file, it is not required to create one.

Install iOS native dependencies with CocoaPods.

cd ios
pod install

Add Jest and Enzyme to Test Your React Native Login

Jest is a library for testing JavaScript apps and Enzyme is a library that makes it easier to select and query elements in tests. They're often used alongside one another.

Install testing dependencies with npm.

npm i [email protected] [email protected] [email protected] [email protected]

Then change your jest key in package.json to match the following:

"jest": {
 "preset": "react-native",
 "automock": false,
 "transformIgnorePatterns": [
   "node_modules/([email protected]|react-native)"
 ],
 "setupFiles": [
   "./setupJest.js"
 ]
}

Create setupJest.js to polyfill React Native for Okta.

// Required to correctly polyfill React-Native

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { NativeModules } from 'react-native';

configure({ adapter: new Adapter() });

global.XMLHttpRequest = jest.fn();
global.fetch = jest.fn();

if (typeof window !== 'object') {
 global.window = global;
 global.window.navigator = {};
}

NativeModules.OktaSdkBridge = {
 createConfig: jest.fn(),
 signIn: jest.fn(),
 signOut: jest.fn(),
 getAccessToken: jest.fn(),
 getIdToken: jest.fn(),
 getUser: jest.fn(),
 isAuthenticated: jest.fn(),
 revokeAccessToken: jest.fn(),
 revokeIdToken: jest.fn(),
 revokeRefreshToken: jest.fn(),
 introspectAccessToken: jest.fn(),
 introspectIdToken: jest.fn(),
 introspectRefreshToken: jest.fn(),
 refreshTokens: jest.fn(),
};

Create Auth.js to handle your authentication code.

import React, { Component, Fragment } from 'react';

import { SafeAreaView, ScrollView, Button, StyleSheet, Text, View } from 'react-native';
import { createConfig, signIn, signOut, isAuthenticated, getUser, getUserFromIdToken, EventEmitter } from '@okta/okta-react-native';
import configFile from './auth.config';

export default class Auth extends Component {
 constructor() {
   super();
   this.state = {
     authenticated: false,
     context: null,
   };
   this.checkAuthentication = this.checkAuthentication.bind(this);
 }

 async componentDidMount() {
   let that = this;
   EventEmitter.addListener('signInSuccess', function (e: Event) {
     that.setState({authenticated: true});
     that.setContext('Logged in!');
   });
   EventEmitter.addListener('signOutSuccess', function (e: Event) {
     that.setState({authenticated: false});
     that.setContext('Logged out!');
   });
   EventEmitter.addListener('onError', function (e: Event) {
     console.warn(e);
     that.setContext(e.error_message);
   });
   EventEmitter.addListener('onCancelled', function (e: Event) {
     console.warn(e);
   });
   await createConfig({
     clientId: configFile.oidc.clientId,
     redirectUri: configFile.oidc.redirectUri,
     endSessionRedirectUri: configFile.oidc.endSessionRedirectUri,
     discoveryUri: configFile.oidc.discoveryUri,
     scopes: configFile.oidc.scopes,
     requireHardwareBackedKeyStore: configFile.oidc.requireHardwareBackedKeyStore,
   });
   this.checkAuthentication();
 }

 componentWillUnmount() {
   EventEmitter.removeAllListeners('signInSuccess');
   EventEmitter.removeAllListeners('signOutSuccess');
   EventEmitter.removeAllListeners('onError');
   EventEmitter.removeAllListeners('onCancelled');
 }

 async componentDidUpdate() {
   this.checkAuthentication();
 }

 async checkAuthentication() {
   const result = await isAuthenticated();
   if (result.authenticated !== this.state.authenticated) {
     this.setState({authenticated: result.authenticated});
   }
 }

 async login() {
   signIn();
 }

 async logout() {
   signOut();
 }

 async getUserIdToken() {
   let user = await getUserFromIdToken();
   this.setContext(JSON.stringify(user, null, 2));
 }

 async getMyUser() {
   let user = await getUser();
   this.setContext(JSON.stringify(user, null, 2));
 }

 setContext = message => {
   this.setState({
     context: message,
   });
 };

 renderButtons() {
   if (this.state.authenticated) {
     return (
       <View style={styles.buttonContainer}>
         <View style={styles.button}>
           <Button
             onPress={async () => {
               this.getUserIdToken();
             }}
             title="Get User From Id Token"
           />
         </View>
       </View>
     );
   }
 }

 render() {
   return (
     <Fragment>
       <SafeAreaView style={styles.container}>
         <View style={styles.buttonContainer}>
           <View style={styles.button}>
             {this.state.authenticated ? (
               <Button
                 style={styles.button}
                 testID="logoutButton"
                 onPress={async () => { this.logout() }}
                 title="Logout"
               />
             ) : (
               <Button
                 style={styles.button}
                 testID="loginButton"
                 onPress={async () => { this.login() }}
                 title="Login"
               />
             )}
           </View>
         </View>
         {this.renderButtons()}
         <ScrollView
           contentInsetAdjustmentBehavior="automatic"
           style={styles.context}>
           <Text>{this.state.context}</Text>
         </ScrollView>
       </SafeAreaView>
     </Fragment>
   );
 }
}

const styles = StyleSheet.create({
 buttonContainer: {
   flexDirection: 'column',
   justifyContent: 'space-between',
 },
 button: {
   width: 300,
   height: 40,
   marginTop: 10,
 },
 container: {
   flex: 1,
   flexDirection: 'column',
   alignItems: 'center',
 }
});

You might notice it imports a config file at the top.

import configFile from './auth.config';

Create auth.config with your OIDC settings from Okta.

export default {
 oidc: {
   clientId: '$yourClientId',
   redirectUri: 'com.okta.dev-#######:/callback',
   endSessionRedirectUri: 'com.okta.dev-#######:/callback',
   discoveryUri: 'https://dev-#######.okta.com/oauth2/default',
   scopes: ['openid', 'profile', 'offline_access'],
   requireHardwareBackedKeyStore: false,
 },
};

Create an app on Okta to get the values for $yourClientId and ######.

  • From the Applications page, choose Add Application.
  • On the Create New Application page, select Native as the platform and click Next.
  • Give your app a memorable name, select Refresh Token as a grant type, and click Done.
  • Click the Edit button and add a Logout redirect URI that matches the default Login redirect URI (e.g., com.okta.dev-123456:/callback).
  • Click Save.

In App.js, import Auth.

import Auth from './Auth';

And use it in a new <View /> after the Hermes logic.

<ScrollView
 contentInsetAdjustmentBehavior="automatic"
 style={styles.scrollView}>
 <Header />
 {global.HermesInternal == null ? null : (
   <View style={styles.engine}>
     <Text style={styles.footer}>Engine: Hermes</Text>
   </View>
 )}
 <View style={styles.body}>
   <View style={styles.sectionContainer}>
     <Text style={styles.sectionTitle}>Step Zero</Text>
     <Text style={styles.sectionDescription}>
       Use <Text style={styles.highlight}>Okta</Text> for
       authentication.
     </Text>
     <Auth />
   </View>

At this point, your tests will not pass because Okta uses an EventEmitter to communicate between components.

Add React Native Authentication Tests

To mock the native event emitter that Okta uses, add a mock for it in __tests__/App-test.js.

/_*
_ @format
*/

import 'react-native';
import React from 'react';
import renderer from 'react-test-renderer';
import App from '../App';

jest.mock(
 '../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter',
);

it('renders correctly', () => {
 renderer.create(<App />);
});

To make sure all the login and authentication logic works, create __tests__/Auth-test.js.

import React from 'react';
import Auth from '../Auth';
import { shallow } from 'enzyme';
import renderer from 'react-test-renderer';
import { waitForState } from 'enzyme-async-helpers';
import { NativeEventEmitter } from 'react-native';

const nativeEmitter = new NativeEventEmitter();

jest
 .mock(
   '../node_modules/react-native/Libraries/Components/StatusBar/StatusBar',
   () => 'StatusBar',
 )
 .mock(
   '../node_modules/react-native/Libraries/Components/ScrollView/ScrollView',
   () => 'ScrollView',
 )
 .mock(
   '../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter',
 );

global.fetch = jest
 .fn()
 .mockImplementation(() => {
   return new Promise((resolve, reject) => {
     resolve({
       json: () => {
         return {
           user: [{ foo: 'foo', bar: 'bar' }],
         }
       },
       ok: true,
     });
   });
 })
 .mockImplementationOnce(() => {
   return new Promise((resolve, reject) => {
     resolve({
       json: () => {
         return {
           userinfo_endpoint: 'dummy_endpoint',
         }
       },
       ok: true,
     });
   });
 });

describe('auth setup', () => {
 it('should render without crashing', () => {
   const rendered = renderer.create(<Auth />).toJSON();
   expect(rendered).toBeTruthy();
 });

 it('should render correctly', () => {
   const rendered = renderer.create(<Auth />).toJSON();
   expect(rendered).toMatchSnapshot();
 });

 it('should initialize with default state', () => {
   const wrapper = shallow(<Auth />);
   expect(wrapper.state().authenticated).toBe(false);
   expect(wrapper.state().context).toBe(null);
 });

 it('should render login button if not authenticated', () => {
   const wrapper = shallow(<Auth />);
   const loginButton = wrapper.find('Button').get(0);
   expect(loginButton.props.title).toBe('Login');
 });

 it('should render logout and get user info buttons if authenticated', () => {
   const wrapper = shallow(<Auth />);
   wrapper.setState({authenticated: true});
   const logoutButton = wrapper.find('Button').get(0);
   const getUserFromIdButton = wrapper.find('Button').get(1);
   const getUserButton = wrapper.find('Button').get(2);
   expect(logoutButton.props.title).toBe('Logout');
   expect(getUserFromIdButton.props.title).toBe('Get User From Id Token');
   expect(getUserButton.props.title).toBe('Get User From Request');
 });

 it('should not render login button if authenticated', () => {
   const wrapper = shallow(<Auth />);
   wrapper.setState({authenticated: true});
   const loginButton = wrapper.find('Button').get(0);
   expect(loginButton.props.title).not.toBe('Login');
 });

 it('should not render logout and get user info buttons if not authenticated', () => {
   const wrapper = shallow(<Auth />);
   const logoutButton = wrapper.find('Button').get(0);
   const getUserFromIdButton = wrapper.find('Button').get(1);
   const getUserButton = wrapper.find('Button').get(2);
   expect(logoutButton.props.title).not.toBe('Logout');
   expect(getUserFromIdButton).toBe(undefined);
   expect(getUserButton).toBe(undefined);
 });
});

describe('authentication flow', () => {
 it('should detect when the user has logged in', async () => {
   const wrapper = shallow(<Auth />);
   const loginButton = wrapper.find('Button').get(0);
   await loginButton.props.onPress();
   expect(loginButton.props.title).toBe('Login');
   nativeEmitter.emit('signInSuccess');
   expect(wrapper.state().authenticated).toBe(true);
   expect(wrapper.state().context).toBe('Logged in!');
 });

 it('should detect when the user has signed out', async () => {
   const wrapper = shallow(<Auth />);
   wrapper.setState({authenticated: true});
   const logoutButton = wrapper.find('Button').get(0);
   await logoutButton.props.onPress();
   expect(logoutButton.props.title).toBe('Logout');
   nativeEmitter.emit('signOutSuccess');
   expect(wrapper.state().authenticated).toBe(false);
   expect(wrapper.state().context).toBe('Logged out!');
 });

 it('should return user profile information from id token', async () => {
   const mockGetIdToken = require('react-native').NativeModules.OktaSdkBridge.getIdToken;
   mockGetIdToken.mockImplementationOnce(() => {
     // id_token returns { a: 'b' }
     return {'id_token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoiYiJ9.jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8'};
   });
   const wrapper = shallow(<Auth />);
   wrapper.setState({authenticated: true});
   const profileButton = wrapper.find('Button').get(1);
   await profileButton.props.onPress();
   await waitForState(wrapper, state => state.context !== null);
   expect(profileButton.props.title).toBe('Get User From Id Token');
   expect(wrapper.state().context).toContain('"a": "b"');
 });
});

Run npm test to bask in the fruits of your labor!

To run your app on iOS, use react-native run-ios.

To run it on Android, you'll need to modify your Gradle build files.

Okta's React Native SDK depends on the Okta OIDC Android library. You have to add this library through Gradle.

Add Okta's BinTray repo to android/build.gradle, under allprojects -> repositories.

maven { url  "https://dl.bintray.com/okta/com.okta.android" }

Make sure your minSdkVersion is 19 in android/build.gradle.

Define a redirect scheme to capture the authorization redirect. In android/app/build.gradle, under android -> defaultConfig, add:

manifestPlaceholders = [ appAuthRedirectScheme: 'com.okta.dev-###### ]

Finally, start a virtual device (or plug in your phone), and run react-native run-android.

Learn More About React Native and OIDC Login

This tutorial showed you how to add a login feature to a React Native application. You learned that OAuth 2.0 is an authorization protocol and OIDC is an authentication layer on top of it. You also used PKCE (Public Key Code Exchange) in your implementation, which is the more secure way to implement OAuth 2.0 in mobile applications.

I hope you enjoy your React Native development journey and its fast refresh feature!

Difference between React.js & React Native

ReactJS or simply React is a JavaScript library that supports both front end and back end efficacies for developing web applications and user interfaces. Whereas React-Native is a JavaScript framework that is used to develop hybrid mobile applications for Android, iOS, and Windows.

ReactJS or simply React is a JavaScript library that supports both front end and back end efficacies for developing web applications and user interfaces. Whereas React-Native is a JavaScript framework that is used to develop hybrid mobile applications for Android, iOS, and Windows.