How to Build Live Multiplayer Quiz App in React Native

In this React Native article, we will learn about How to Build Live Multiplayer Quiz App in React Native. In this tutorial, we’ll create a quiz app which can cater to multiple users in realtime.

Prerequisites

Knowledge of Node.js and React Native is required to follow this tutorial. This also means your machine needs to have the React Native development environment.

We’ll be using Yarn to install dependencies.

You’ll also need a Pusher app instance and an ngrok account. Enable client events on your Pusher app so we can trigger events from the app itself.

The following package versions are used in this tutorial:

  • Node 11.2.0
  • Yarn 1.13.0
  • React Native 0.58.5
     

App overview

We will create a multi-player quiz app. Users will be given 10 multiple choice questions and they have to select the correct answer to each one as they are displayed on the screen.

When the user opens the app, they have to log in. This serves as their identification in the game:

react-native-quiz-1

Once they’re logged in, a loading animation will be displayed while waiting for the admin to trigger the questions.

The game starts when the first question is displayed on the screen. As soon as the user picks an option, either correct or wrong mark will be displayed next to the option they selected. Once the user selects an option, they can no longer select another one. Users have 10 seconds to answer each question. If they answer after the countdown (displayed in the upper right corner), their answer won’t be considered.

react-native-quiz-2

After all 10 questions have been displayed, the top users are displayed and that ends the game:

react-native-quiz-3

Setting up

Clone the repo and switch to the starter branch to save time in setting up the app and adding boilerplate code:

    git clone https://github.com/anchetaWern/RNQuiz
    cd RNQuiz
    git checkout starter

Next, install the dependencies and link them up:

    yarn
    react-native eject
    react-native link react-native-config
    react-native link react-native-gesture-handler
    react-native link react-native-vector-icons

The starter branch already has the two pages set up. All the styles that the app will use are also included. So all we have to do is add the structure and logic.

Next, update your android/app/src/main/AndroidManifest.xml and add the permission for accessing the network state. This is required by Pusher:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.rnquiz">
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <!-- add this -->
    </manifest>

Next, update android/app/build.gradle to include the .gradle file for the React Native Config package. We’ll be using it to use .env configuration files inside the project:

    apply from: "../../node_modules/react-native/react.gradle"
    apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"

Next, create a .env file at the root of the React Native project and add your Pusher app credentials:

    PUSHER_APP_KEY="YOUR PUSHER APP KEY"
    PUSHER_APP_CLUSTER="YOUR PUSHER APP CLUSTER"

Once you’re done with setting up the app, do the same for the server as well:

    cd server
    yarn

The server doesn’t have boilerplate code already set up so we’ll write everything from scratch.

Lastly, create a server/.env file and add your Pusher app credentials:

    APP_ID="YOUR PUSHER APP ID"
    APP_KEY="YOUR PUSHER APP KEY"
    APP_SECRET="YOUR PUSHER APP SECRET"
    APP_CLUSTER="YOUR PUSHER APP CLUSTER"

Quiz server

Before we add the code for the actual app, we have to create the server first. This is where we add the code for creating the database and displaying the UI for creating quiz items.

Navigate inside the server directory if you haven’t already. Inside, create an index.js file and add the following:

    const express = require("express"); // server framework
    const bodyParser = require("body-parser"); // for parsing the form data
    const Pusher = require("pusher"); // for sending realtime messages
    const cors = require("cors"); // for accepting requests from any host
    const mustacheExpress = require('mustache-express'); // for using Mustache for templating
    
    const { check } = require('express-validator/check'); // for validating user input for the quiz items
    
    const sqlite3 = require('sqlite3').verbose(); // database engine
    const db = new sqlite3.Database('db.sqlite'); // database file in the root of the server directory

Next, add the code for using the server packages we’ve imported above:

    const app = express();
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(cors());
    app.engine('mustache', mustacheExpress());
    app.set('view engine', 'mustache');
    app.set('views', __dirname + '/views'); // set the location of mustache files

Set up Pusher:

    const pusher = new Pusher({
      appId: process.env.APP_ID,
      key: process.env.APP_KEY,
      secret: process.env.APP_SECRET,
      cluster: process.env.APP_CLUSTER
    });

Next, add the code for authenticating users with Pusher and logging them into the server:

    var users = []; // this will store the username and scores for each user
    
    app.post("/pusher/auth", (req, res) => {
      const socketId = req.body.socket_id;
      const channel = req.body.channel_name;
    
      const auth = pusher.authenticate(socketId, channel);
      res.send(auth);
    });
    
    app.post("/login", (req, res) => {
      const username = req.body.username;
      console.log(username + " logged in");
    
      if (users.indexOf(username) === -1) { // check if user doesn't already exist
        console.log('users: ', users.length);
        users.push({
          username,
          score: 0 // initial score
        });
      }
    
      res.send('ok');
    });

Next, add the code for creating the database. Note that this step is optional as I have already added the db.sqlite file at the root of the server directory. That’s the database file which contains a few questions that I used for testing. If you want to start anew, simply create an empty db.sqlite file through the command line (or your text editor) and access the below route on your browser:

    app.get("/create-db", (req, res) => {
      db.serialize(() => {
        db.run('CREATE TABLE [quiz_items] ([question] VARCHAR(255), [optionA] VARCHAR(255), [optionB] VARCHAR(255), [optionC] VARCHAR(255), [optionD] VARCHAR(255), [answer] CHARACTER(1))');
      });
    
      db.close();
      res.send('ok');
    });

Next, add the route for displaying the UI for adding quiz items. This uses the Mustache Express library to render the quiz_creator template inside the views folder:

    app.get("/create-quiz", (req, res) => {
      res.render('quiz_creator');
    });

Here’s the code for the quiz creator template. Create a views/quiz_creator.mustache file and add the following:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8"/>
      <title>Quiz Creator</title>
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
      <style>
      .hidden {
        display: none;
      }
      </style>
    </head>
    
    <body>
    
      <div class="container">
        <div class="row align-items-center">
          <div class="col col-lg-12">
            <h1>Create Quiz</h1>
    
            <div class="alert alert-success hidden">
            Item created!
            </div>
    
            <form method="POST" action="/save-item">
              <div class="form-group">
                <label for="question">Question</label>
                <input type="text" id="question" name="question" class="form-control" required>
              </div>
    
              <div class="form-group">
                <label for="option_a">Option A</label>
                <input type="text" id="option_a" name="option_a" class="form-control" required>
              </div>
    
              <div class="form-group">
                <label for="option_b">Option B</label>
                <input type="text" id="option_b" name="option_b" class="form-control" required>
              </div>
    
              <div class="form-group">
                <label for="option_c">Option C</label>
                <input type="text" id="option_c" name="option_c" class="form-control" required>
              </div>
    
              <div class="form-group">
                <label for="option_d">Option D</label>
                <input type="text" id="option_d" name="option_d" class="form-control" required>
              </div>
    
              Correct Answer
    
              <div class="form-group">
                <div class="form-check">
                  <input class="form-check-input" type="radio" name="answer" id="correct_a" value="A">
                  <label class="form-check-label" for="correct_a">
                    A
                  </label>
                </div>
    
                <div class="form-check">
                  <input class="form-check-input" type="radio" name="answer" id="correct_b" value="B">
                  <label class="form-check-label" for="correct_b">
                    B
                  </label>
                </div>
    
                <div class="form-check">
                  <input class="form-check-input" type="radio" name="answer" id="correct_c" value="C">
                  <label class="form-check-label" for="correct_c">
                    C
                  </label>
                </div>
    
                <div class="form-check">
                  <input class="form-check-input" type="radio" name="answer" id="correct_d" value="D">
                  <label class="form-check-label" for="correct_d">
                    D
                  </label>
                </div>
              </div>
    
              <button type="submit" class="btn btn-primary">Save Item</button>
            </form>
          </div>
        </div>
      </div>
    
      <script>
        if (window.location.hash) {
          document.querySelector('.alert').classList.remove('hidden');
        }
      </script>
    
    </body>
    </html>

Note that we haven’t really used the templating engine in the above template. But it’s a good practice to use it if you’re expecting to display dynamic data.

Next, add the route where the form data will be submitted. This has a simple validation where the length of each text field should not be less than one. Once the data is validated, we insert a new quiz item to the table:

    // server/index.js
    const required = { min: 1 }; // minimum number of characters required for each field
    
    app.post("/save-item", [
      check('question').isLength(required),
      check('option_a').isLength(required),
      check('option_b').isLength(required),
      check('option_c').isLength(required),
      check('option_d').isLength(required),
      check('answer').isLength(required) // the letter of the answer (e.g. A, B, C, D)
    ], (req, res) => {
    
      const { question, option_a, option_b, option_c, option_d, answer } = req.body;
      db.serialize(() => {
        var stmt = db.prepare('INSERT INTO quiz_items VALUES (?, ?, ?, ?, ?, ?)');
        stmt.run([question, option_a, option_b, option_c, option_d, answer]);
      });
    
      res.redirect('/create-quiz#ok'); // redirect back to the page for creating a quiz item
    });

Next, add the code for sending the questions. This selects ten random rows from the table and sends them at an interval (every 13 seconds). The users will only have ten seconds to answer each question, but we included an additional three seconds to cater for the latency (delay) in the network and in the app:

    const channel_name = 'quiz-channel';
    const question_timing = 13000; // 10 secs to show + 3 secs latency
    const question_count = 10;
    const top_users_delay = 10000; // additional delay between displaying the last question and the top users
    
    app.get("/questions", (req, res) => {
      var index = 1;
      db.each('SELECT question, answer, optionA, optionB, optionC, optionD, answer FROM quiz_items ORDER BY random() LIMIT ' + question_count, (err, row) => {
        timedQuestion(row, index);
        index += 1;
      });
    
      // next: add code for sending top users
    
      res.send('ok');
    });
    
    // next: add code for timedQuestion function

After all the questions have been sent, we send the top three users to all users who are currently subscribed to the quiz channel:

    setTimeout(() => {
      console.log('now triggering score...');
      const sorted_users_by_score = users.sort((a, b) => b.score - a.score)
      const top_3_users = sorted_users_by_score.slice(0, 1); // replace 1 with 3
    
      pusher.trigger(channel_name, 'top-users', {
        users: top_3_users
      });
    }, (question_timing * (question_count + 2)) + top_users_delay);

Here’s the code for the timedQuestion function we used earlier. All it does is send each individual row from the table:

    const timedQuestion = (row, index) => {
      setTimeout(() => {
        Object.assign(row, { index });
    
        pusher.trigger(
          channel_name,
          'question-given',
          row
        );
    
      }, index * question_timing);
    }

Next, add the route for incrementing user scores. This finds the user with the specified username in the array of users and then increments their score:

    app.post("/increment-score", (req, res) => {
      const { username } = req.body;
      console.log(`incremented score of ${username}`);
    
      const user_index = users.findIndex(user => user.username == username);
      users[user_index].score += 1;
    
      res.send('ok');
    });

Note that all users make a request to the above route every time they answer correctly so it’s a potential bottleneck. This is especially true if there are thousands of users using the app at the same time. If you’re planning to create a multi-player quiz app of your own, you might want to use Pusher on the server side to listen for messages sent by users. From there, you can increment their scores as usual.

Lastly, run the server on a specific port:

    var port = process.env.PORT || 5000;
    app.listen(port);

Quiz app

Now that we’ve added the server code, we’re ready to work on the actual app. As mentioned earlier, the boilerplate code has already been set up so all we have to do is add the UI structure and the logic.

Login screen

Open the login screen file and add the following:

    // src/screens/Login.js
    import React, { Component } from "react";
    import { View, Text, TextInput, TouchableOpacity, Alert } from "react-native";
    
    import Pusher from "pusher-js/react-native"; // for using Pusher
    import Config from "react-native-config"; // for using .env config file
    
    import axios from 'axios'; // for making http requests
    
    const pusher_app_key = Config.PUSHER_APP_KEY;
    const pusher_app_cluster = Config.PUSHER_APP_CLUSTER;
    const base_url = "YOUR NGROK HTTPS URL";
    
    class LoginScreen extends Component {
      static navigationOptions = {
        header: null
      };
    
      state = {
        username: "",
        enteredQuiz: false
      };
    
      constructor(props) {
        super(props);
        this.pusher = null;
      }
    
      // next: add render()
    }
    
    export default LoginScreen;

Next, render the login UI:

    render() {
      return (
        <View style={styles.wrapper}>
          <View style={styles.container}>
            <View style={styles.main}>
              <View>
                <Text style={styles.label}>Enter your username</Text>
                <TextInput
                  style={styles.textInput}
                  onChangeText={username => this.setState({ username })}
                  value={this.state.username}
                />
              </View>
    
              {!this.state.enteredQuiz && (
                <TouchableOpacity onPress={this.enterQuiz}>
                  <View style={styles.button}>
                    <Text style={styles.buttonText}>Login</Text>
                  </View>
                </TouchableOpacity>
              )}
    
              {this.state.enteredQuiz && (
                <Text style={styles.loadingText}>Loading...</Text>
              )}
            </View>
          </View>
        </View>
      );
    }

When the user clicks on the login button, we authenticate them via Pusher and log them into the server. As you’ve seen in the server code earlier, this allows us to add the user to the users array which is then used later to filter for the top users:

    enterQuiz = async () => {
      const myUsername = this.state.username;
    
      if (myUsername) {
        this.setState({
          enteredQuiz: true // show loading animation
        });
    
        this.pusher = new Pusher(pusher_app_key, {
          authEndpoint: `${base_url}/pusher/auth`,
          cluster: pusher_app_cluster,
          encrypted: true
        });
        
        try {
          await axios.post(
            `${base_url}/login`, 
            {
              username: myUsername
            }
          );
          console.log('logged in!');
        } catch (err) {
          console.log(`error logging in ${err}`);
        }
        
        // next: add code for subscribing to quiz channel
    
      }
    };

Next, listen for Pusher’s channel subscription success event and navigate the user to the Quiz screen. We pass the Pusher reference, username and quiz channel as navigation params so we can also use it in the Quiz screen:

    this.quizChannel = this.pusher.subscribe('quiz-channel');
    this.quizChannel.bind("pusher:subscription_error", (status) => {
      Alert.alert(
        "Error",
        "Subscription error occurred. Please restart the app"
      );
    });
    
    this.quizChannel.bind("pusher:subscription_succeeded", () => {     
      this.props.navigation.navigate("Quiz", {
        pusher: this.pusher,
        myUsername: myUsername,
        quizChannel: this.quizChannel
      });
    
      this.setState({
        username: "",
        enteredQuiz: false // hide loading animation
      });
    });

Quiz screen

The Quiz screen is the main meat of the app. This is where the questions are displayed for the user to answer. Start by importing all the packages we need:

    // src/screens/Quiz.js
    import React, { Component } from "react";
    import { View, Text, ActivityIndicator, TouchableOpacity } from "react-native";
    import axios from 'axios';
    import Icon from 'react-native-vector-icons/FontAwesome';
    
    const option_letters = ['A', 'B', 'C', 'D'];
    const base_url = "YOUR NGROK HTTPS URL";

Next, initialize the state:

    class Quiz extends Component {
      
      static navigationOptions = {
        header: null
      };
    
      state = {
        display_question: false, // whether to display the questions or not
        countdown: 10, // seconds countdown for answering the question
        show_result: false, // whether to show whether the user's answer is correct or incorrect
        selected_option: null, // the last option (A, B, C, D) selected by the user
        disable_options: true, // whether to disable the options from being interacted on or not
        total_score: 0, // the user's total score
       
        index: 1, // the index of the question being displayed
        display_top_users: false // whether to display the top users or not
      }
    
      // next: add constructor
    }
    
    export default Quiz;

Inside the constructor, we get the navigation params that were passed from the login screen earlier. Then we listen for the question-given event to be triggered by the server. As you’ve seen earlier, this contains the question data (question, four options, and answer). We just set those into the state so they’re displayed. After that, we immediately start the countdown so that the number displayed on the upper right corner counts down every second:

    constructor(props) {
      super(props);
      const { navigation } = this.props;
      
      this.pusher = navigation.getParam('pusher');
      this.myUsername = navigation.getParam('myUsername');
      this.quizChannel = navigation.getParam('quizChannel');
    
      this.quizChannel.bind('question-given', ({ index, question, optionA, optionB, optionC, optionD, answer }) => {
        
        this.setState({
          display_question: true, // display the question in the UI
          countdown: 10, // start countdown
          selected_option: null,
          show_result: false, 
          disable_options: false,
          
          // question to display
          index, 
          question, 
          optionA, 
          optionB, 
          optionC, 
          optionD, 
          answer
        });
        
        // start the countdown
        const interval = setInterval(() => {
          this.setState((prevState) => {
            const cnt = (prevState.countdown > 0) ? prevState.countdown - 1 : 0
            if (cnt == 0) {
              clearInterval(interval);
            }
    
            return {
              countdown: cnt
            }
          });
        }, 1000);
    
      });
      
      // next: add listener for top users
    }

Next, listen for the top-users event. This will display the names and scores of the top users:

    this.quizChannel.bind('top-users', ({ users }) => {
      console.log('received top users: ', JSON.stringify(users));
      this.setState({
        top_users: users,
        display_top_users: true
      });
    });

Next, render the UI. When the user is first redirected from the login screen, only the total score, default countdown value, and the activity indicator are displayed. When the server starts sending questions, the activity indicator is hidden in place of the question and its options. Lastly, when the server sends the top users, the question and its options are hidden in place of the list of top users:

    render() {
      const { 
        total_score,
        countdown, 
        index, 
        question, 
        optionA, 
        optionB, 
        optionC, 
        optionD, 
        answer, 
    
        display_question,
        top_users,
        display_top_users
      } = this.state;
      
      const options = [optionA, optionB, optionC, optionD];
    
      return (
        <View style={styles.container}>
          
          <View>
            <Text>Total Score: {total_score}</Text>
          </View>
    
          <View style={styles.countdown}>
            <Text style={styles.countdown_text}>{countdown}</Text>
          </View>
    
          {
            !display_question &&
            <View style={styles.centered}>
              <ActivityIndicator size="large" color="#0000ff" />
            </View>
          }
    
          {
            display_question && !display_top_users && 
            <View style={styles.quiz}>
              {
                !showAnswer &&
                <View>
                  <View>
                    <Text style={styles.big_text}>{question}</Text>
                  </View>
    
                  <View style={styles.list_container}>
                    { this.renderOptions(options, answer) }
                  </View>
                </View>
              }
            </View>
          }
    
          {
            display_top_users &&
            <View style={styles.top_users}>
              <Text style={styles.big_text}>Top Users</Text>
              <View style={styles.list_container}>
              { this.renderTopUsers() }
              </View>
            </View>
          }
              
        </View>
      );
    }

Here’s the code for rendering the options. Each one executes the placeAnswer function when the user clicks on it. As soon as an option is selected, the icon which represents whether they’re correct or not is immediately displayed next to it:

    renderOptions = (options, answer) => {
      const { show_result, selected_option, disable_options } = this.state;
    
      return options.map((opt, index) => {
        const letter = option_letters[index];
        const is_selected = selected_option == letter;
        const is_answer = (letter == answer) ? true : false; 
    
        return (
          <TouchableOpacity disabled={disable_options} onPress={() => this.placeAnswer(index, answer)} key={index}>
            <View style={styles.option}>
              <Text style={styles.option_text}>{opt}</Text>
    
              {
                is_answer && show_result && is_selected && <Icon name="check" size={25} color="#28a745" />
              }
              
              {
                !is_answer && show_result && is_selected && <Icon name="times" size={25} color="#d73a49" />
              }
            </View>
          </TouchableOpacity>
        );
      });
    }

Here’s the placeAnswer function. This accepts the index of the selected option (0, 1, 2, or 3) and the letter of the answer. Those are used to determine if the user answered correctly or not. The answer isn’t even considered if the user missed the countdown. If they answered correctly, their total score is incremented by one and the app makes a request to the server to increment the user’s score:

    placeAnswer = (index, answer) => {
      
      const selected_option = option_letters[index]; // the letter of the selected option
      const { countdown, total_score } = this.state;
    
      if (countdown > 0) { // 
        if (selected_option == answer) { 
          this.setState((prevState) => {
            return {
              total_score: prevState.total_score + 1
            }
          });
      
          axios.post(base_url + '/increment-score', {
            username: this.myUsername
          }).then(() => {
            console.log('incremented score');
          }).catch((err) => {
            console.log('error occurred: ', e);
          });
        } 
      }
    
      this.setState({
        show_result: true, // show whether the user answered correctly or not
        disable_options: true, // disallow the user from selecting any of the options again
        selected_option // the selected option (letter)
      });
    }

Here’s the code for rendering the top users:

    renderTopUsers = () => {
      const { top_users } = this.state;
      return top_users.map(({ username, score }) => {
        return (
          <View key={username}>
            <Text style={styles.sub_text}>{username}: {score} out of 10</Text>
          </View>
        );
      });
    }

Running the app

To run the app, you have to run the server first and expose it to the internet by using ngrok:

    cd server
    yarn start
    ~/.ngrok http 5000

If you haven’t used the db.sqlite file I provided in the repo, you have to access http://localhost:5000/create-db to create the database (Note: you first have to create an empty db.sqlite at the root of the server directory). After that, access http://localhost:5000/create-quiz and add some quiz items. Add at least 10 items.

Next, update your src/screens/Login.js and src/screens/Quiz.js file with your ngrok HTTPS URL and run the app:

    react-native run-android
    react-native run-ios

Lastly, access http://localhost:5000/questions to start sending the quiz items.

Conclusion

In this tutorial, we’ve created a multi-player quiz app using Node.js and React Native. Along the way, you learned how to use mustache templates and SQLite database within an Express app. Lastly, you learned how to use Node.js, React Native, and Pusher to easily implement a multi-player quiz app.

Original article sourced at: https://pusher.com

#react 

What is GEEK

Buddha Community

How to Build Live Multiplayer Quiz App in React Native
Autumn  Blick

Autumn Blick

1598839687

How native is React Native? | React Native vs Native App Development

If you are undertaking a mobile app development for your start-up or enterprise, you are likely wondering whether to use React Native. As a popular development framework, React Native helps you to develop near-native mobile apps. However, you are probably also wondering how close you can get to a native app by using React Native. How native is React Native?

In the article, we discuss the similarities between native mobile development and development using React Native. We also touch upon where they differ and how to bridge the gaps. Read on.

A brief introduction to React Native

Let’s briefly set the context first. We will briefly touch upon what React Native is and how it differs from earlier hybrid frameworks.

React Native is a popular JavaScript framework that Facebook has created. You can use this open-source framework to code natively rendering Android and iOS mobile apps. You can use it to develop web apps too.

Facebook has developed React Native based on React, its JavaScript library. The first release of React Native came in March 2015. At the time of writing this article, the latest stable release of React Native is 0.62.0, and it was released in March 2020.

Although relatively new, React Native has acquired a high degree of popularity. The “Stack Overflow Developer Survey 2019” report identifies it as the 8th most loved framework. Facebook, Walmart, and Bloomberg are some of the top companies that use React Native.

The popularity of React Native comes from its advantages. Some of its advantages are as follows:

  • Performance: It delivers optimal performance.
  • Cross-platform development: You can develop both Android and iOS apps with it. The reuse of code expedites development and reduces costs.
  • UI design: React Native enables you to design simple and responsive UI for your mobile app.
  • 3rd party plugins: This framework supports 3rd party plugins.
  • Developer community: A vibrant community of developers support React Native.

Why React Native is fundamentally different from earlier hybrid frameworks

Are you wondering whether React Native is just another of those hybrid frameworks like Ionic or Cordova? It’s not! React Native is fundamentally different from these earlier hybrid frameworks.

React Native is very close to native. Consider the following aspects as described on the React Native website:

  • Access to many native platforms features: The primitives of React Native render to native platform UI. This means that your React Native app will use many native platform APIs as native apps would do.
  • Near-native user experience: React Native provides several native components, and these are platform agnostic.
  • The ease of accessing native APIs: React Native uses a declarative UI paradigm. This enables React Native to interact easily with native platform APIs since React Native wraps existing native code.

Due to these factors, React Native offers many more advantages compared to those earlier hybrid frameworks. We now review them.

#android app #frontend #ios app #mobile app development #benefits of react native #is react native good for mobile app development #native vs #pros and cons of react native #react mobile development #react native development #react native experience #react native framework #react native ios vs android #react native pros and cons #react native vs android #react native vs native #react native vs native performance #react vs native #why react native #why use react native

Top 10 React Native App Development Companies in USA

React Native is the most popular dynamic framework that provides the opportunity for Android & iOS users to download and use your product. Finding a good React Native development company is incredibly challenging. Use our list as your go-to resource for React Native app development Companies in USA.

List of Top-Rated React Native Mobile App Development Companies in USA:

  1. AppClues Infotech
  2. WebClues Infotech
  3. AppClues Studio
  4. WebClues Global
  5. Data EximIT
  6. Apptunix
  7. BHW Group
  8. Willow Tree:
  9. MindGrub
  10. Prismetric

A Brief about the company details mentioned below:

1. AppClues Infotech
As a React Native Mobile App Development Company in USA, AppClues Infotech offers user-centered mobile app development for iOS & Android. Since their founding in 2014, their React Native developers create beautiful mobile apps.

They have a robust react native app development team that has high knowledge and excellent strength of developing any type of mobile app. They have successfully delivered 450+ mobile apps as per client requirements and functionalities.
Website: https://www.appcluesinfotech.com/

2. WebClues Infotech
WebClues Infotech is the Top-Notch React Native mobile app development company in USA & offering exceptional service worldwide. Since their founding in 2014, they have completed 950+ web & mobile apps projects on time.

They have the best team of developers who has an excellent knowledge of developing the most secure, robust & Powerful React Native Mobile Apps. From start-ups to enterprise organizations, WebClues Infotech provides top-notch React Native App solutions that meet the needs of their clients.
Website: https://www.webcluesinfotech.com/

3. AppClues Studio
AppClues Studio is one of the top React Native mobile app development company in USA and offers the best service worldwide at an affordable price. They have a robust & comprehensive team of React Native App developers who has high strength & extensive knowledge of developing any type of mobile apps.
Website: https://www.appcluesstudio.com/

4. WebClues Global
WebClues Global is one of the best React Native Mobile App Development Company in USA. They provide low-cost & fast React Native Development Services and their React Native App Developers have a high capability of serving projects on more than one platform.

Since their founding in 2014, they have successfully delivered 721+ mobile app projects accurately. They offer versatile React Native App development technology solutions to their clients at an affordable price.
Website: https://www.webcluesglobal.com/

5. Data EximIT
Hire expert React Native app developer from top React Native app development company in USA. Data EximIT is providing high-quality and innovative React Native application development services and support for your next projects. The company has been in the market for more than 8 years and has already gained the trust of 553+ clients and completed 1250+ projects around the globe.

They have a large pool of React Native App developers who can create scalable, full-fledged, and appealing mobile apps to meet the highest industry standards.
Website: https://www.dataeximit.com/

6. Apptunix
Apptunix is the best React Native App Development Company in the USA. It was established in 2013 and vast experience in developing React Native apps. After developing various successful React Native Mobile Apps, the company believes that this technology helps them incorporate advanced features in mobile apps without influencing the user experience.
Website: https://www.apptunix.com/

7. BHW Group
BHW Group is a Top-Notch React Native Mobile App Development Company in the USA. The company has 13+ years of experience in providing qualitative app development services to clients worldwide. They have a compressive pool of React Native App developers who can create scalable, full-fledged, and creative mobile apps to meet the highest industry standards.
Website: https://thebhwgroup.com/

8. Willow Tree:
Willow Tree is the Top-Notch React Native Mobile App Development Company in the USA & offering exceptional React Native service. They have the best team of developers who has an excellent knowledge of developing the most secure, robust & Powerful React Native Mobile Apps. From start-ups to enterprise organizations, Willow Tree has top-notch React Native App solutions that meet the needs of their clients.
Website: https://willowtreeapps.com/

9. MindGrub
MindGrub is a leading React Native Mobile App Development Company in the USA. Along with React Native, the company also works on other emerging technologies like robotics, augmented & virtual reality. The Company has excellent strength and the best developers team for any type of React Native mobile apps. They offer versatile React Native App development technology solutions to their clients.
Website: https://www.mindgrub.com/

10. Prismetric
Prismetric is the premium React Native Mobile App Development Company in the USA. They provide fast React Native Development Services and their React Native App Developers have a high capability of serving projects on various platforms. They focus on developing customized solutions for specific business requirements. Being a popular name in the React Native development market, Prismetric has accumulated a specialty in offering these services.
Website: https://www.prismetric.com/

#top rated react native app development companies in usa #top 10 react native app development companies in usa #top react native app development companies in usa #react native app development technologies #react native app development #hire top react native app developers in usa

Hire Top-Notch React Native App Developers in USA

Do you want to hire talented & highly skilled React Native mobile app developers in USA? AppClues Infotech has the best team of dedicated React Native App designers & developers that provide the complete React Native solution & listed the top-notch USA-based companies list for your kind information.

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#hire best react native app developers in usa #hire react native mobile app developers #top react native development companies #top react native app development company in usa #best react native app development services provider company #custom react native app development company

Top Rated React Native Development Agency

AppClues Infotech is a premier & leading React Native app Development Company in USA having highly skilled React Native app developers offering robust services with the latest technology & functionalities.

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#react native app development company #top react native app development company in usa #best react native app development services usa #react native mobile development #react native mobile development #top react native app development companies usa

React Native Mobile App Development

React Native is a framework that allows you to build mobile applications for both Android and iOS platforms using a similar codebase. This can shorten the development time and reduce the overall cost of building mobile apps.

Looking to create Mobile Applications but low in the budget? Contact Skenix Infotech now to get the most effective React Native Mobile App Development Services.

#react native development #mobile app development #react native ios app #react native ui #react native mobile app #react native