Master React Native + Node J.JS + GraphQL

How to Create Application in React Native with Node.js backend and GraphQL

Quick Summary: To create an application in React Native with a Node.js backend and GraphQL, follow these steps: set up the React Native environment, configure the Node.js backend, integrate GraphQL for efficient data fetching, and connect the frontend and backend. Use tools like GraphQL for testing and debugging GraphQL queries. Combining these technologies enables the development of cutting-edge and high-performance mobile applications.

Introduction

You need clarification on whether you want to go towards fast application development with the backend. What framework or technology should you select? Hence, you are right to be here. An application in React Native with a Node.js backend is a perfect combination for software development.

Creating a mobile app using React Native is a perfect solution for fast and effective development.

We will explain every topic with an example with minimum complexity that helps you build a cross-platform application with a backend.

⇒ In this example, we will use React Native (for the app), Node.js (the backend API), and MongoDB (for the database).

So, hang on and read how you can create an application in React Native with a Node.js backend and GraphQL. Moreover, you can also create an application in React Native with our React Native Development Services.

What Is React Native?

For developing an application in React Native you must know all about it. But As a tech enthusiast, you all already know what React Native is, and If you are new to React Native, then learn it from the React Native development page.

Set Up An Environment For React Native

To build an application in React Native, you must first set up an environment. And the easiest way to set up an environment for React Native

Why React Native?

There are many benefits for building an application in React Native, some of them are below:

  • Cross-platform Versatility: By using React Native, you can create applications with a single codebase that works flawlessly on both the iOS and Android platforms. It dramatically shortens the development process and lowers time and expense.
  • Improved Native-Like Performance: By utilizing native components, React Native allows you to achieve outstanding performance for your app, giving consumers a fluid and responsive experience.
  • React Native with a Node.js combination for seamless frontend-backend integration. The js backend creates a seamless connection between the two, enabling real-time data changes and increasing user engagement.
  • GraphQL-enabled Data Fetching: By implementing GraphQL, your application can simplify data fetching and enable users only to request the precise data they require. This optimization reduces data inefficiencies, producing a better-performing app.
  • A thriving ecosystem and community: React Native, Node.js, and GraphQL have active and helpful communities. You’ll have access to many libraries, resources, and tools that provide continuing support and upgrades for your project.
  • Accelerated Development Cycles: You can quickly launch your application thanks to the synergy between React Native and GraphQL and the flexibility of Node.js.

By embracing this powerful technological stack, you may build a React Native app which will be effective and scalable. And it also supports a varied user base across numerous platforms.

What is Node.js?

Node.js is a powerful open-source JavaScript runtime. Its goal is to make it possible for programmers to run JavaScript code outside of a web browser, which makes it particularly well-suited for server-side applications.

The framework has an event-driven, non-blocking architecture, a crucial aspect that enables it to manage multiple connections and I/O operations effectively. Node.js has gained substantial appeal for building web servers, APIs, and a wide range of applications because of its lightweight and scalable features and robust library ecosystem.

Why Node.js?

When designing applications in React Native with a Node.js backend and GraphQL, Node.js is a fantastic solution. It is the perfect framework for building reliable and practical mobile apps due to its adaptability, scalability, and simple connection with JavaScript. By hiring Node.Js developers, you can quickly get all things done. Along with that, there are various reasons to choose Node.Js.

First, Node.js features an event-driven, non-blocking architecture that efficiently processes multiple concurrent requests. Real-time data syncing is possible by this functionality, significantly improving the overall usability of React Native app development services.

Combining Node.js and React Native makes sharing code between the front and backend easier, cutting down on development time. It also streamlines the development process by using the same ecosystem and language, and improves team communication.

Additionally, Node.js has a well-known package management called NPM that provides a wide range of open-source libraries and modules. This extensive ecosystem offers pre-built solutions for developers, speeding up development and addressing frequent issues.

Last, developers can achieve compelling data fetching by combining GraphQL with Node.js, providing more flexibility and reducing over-fetching concerns sometimes experienced in conventional REST APIs. It thus leads to quicker data retrieval and less network utilization, which eventually improves the performance of React Native apps.

How to create a basic API in Node.Js backend?

I will explain this with an example, but you want to know only Node.Js backend API

Set up Environment for Node.Js

I hope you are also ready with the Node.Js environment setup. It only requires installing node & npm, click here to know more.

Set up Environment for MongoDB

Visit MongoDB’s official website & follow the steps to set up MongoDB on your local PC, or you can use the cloud database of MongoDB Alas.

What is GraphQL?

GraphQL is an open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data.

In simple language, if I explain, GraphQL works as a carrier of data between Backend & Frontend, which means we will create API in Node.Js & Application in React Native as usual, but to call Rest APIs we will use GraphQL instead of manual calling with Axios or fetch.

Start MongoDB, Create backend project, Install required libraries & Implement Backend code

Now we are ready to start after all environments are set up.

Here we are going to build an Application with a frontend & backend. So first we will start to develop basic backend APIs for Book & Author. We will not implement complicated things. So let’s start.

So let’s start

Here I am assuming you have completed all the setup. After that, we will follow steps to start MongoDB in the local machine( I am doing all the things in MacOs)

Step-1: Open terminal and this fire below command to in MongoDB directory.

cd /usr/local/var/log/mongodb [if Intel Processor]
                         
                         cd /opt/homebrew/var/log/mongodb [if Apple M1 Processor]

Step-2: Fire the below command to start the MongoDB database server locally brew services start [email protected] After your work is done, if you want to stop MongoDB then fire the below command in the same path brew services stop [email protected]

Step-3: Here we will start to create APIs in Node.Js & Connect the MongoDB database.

    • Create a folder for your project I named “LibraryM_backend”, you can name anything as you want.
    • Open that folder path in terminal & fire command npm init -y. After this command, you can see a package.json file in your folder. And after that, we will install all required libraries (npm packages)
    • We will install the below packages.
      • npm install mongoose
      • npm install express
    • Create an index.js file in the root directory of a project like “/LibraryM_backend/index.js” and paste the following code.
    • const express = require('express');
                               const mongoose = require('mongoose');
                               const app = express();
                               //Establish database connection
                               const connectDb = async () => {
                               await mongoose.connect('mongodb://localhost:27017/book_db', {
                               useUnifiedTopology: true,
                               useNewUrlParser: true
                               }).then(() => {
                               console.log("DB connected successfully....");
                               }).catch(() => {
                               console.log("DB connection failed...");
                               })
                               }
                               connectDb()
                               //listening server on port 4000
                               app.listen(4000, () => {
                               console.log("Server is running on port: 4000");
                               })
    • Mongoose. Connect is connecting to the “book_db” MongoDB database. If you already create that, combine it with the existing one; otherwise, create a new one & then click “mongodb://localhost:27017/book_db” as a connection string to connect with the MongoDB database.
  • Run command npm start & you will find in console “Server is running on port: 4000”.
  • Here every time we will need to start the server after changes to get reflect changes, to avoid this we need to install a dev dependency nodemon: npm install –save-dev nodemon
  • Change the following code in package.json
  • "scripts": {
                                "test": "echo \"Error: no test specified\" && exit 1",
                                "dev": "nodemon server.js"
                             },
  • Now we are done with the database connection & server started.

Integrate GraphQL in backend side (Using Apollo Server)

After we will install npm for GraphQL
npm install apollo-server
npm install graphql

What is Apollo Server?

Apollo Server is an open-source, spec-compliant GraphQL server that’s compatible with any GraphQL client, including Apollo Client. It’s the best way to build a production-ready, self-documenting GraphQL API that can use data from any source.

In simple language, Apollo Server is used on Backend Side, and Apollo Client is used on Frontend Side(React JS, React Native, or other frameworks). So Apollo Client makes it enabled to interact with backend APIs.

Apollo Server

Create folder structure for backend

I will create a folder structure like below. You can create according to your convenience.

Create Folder Structure For Backend

Configure Apollo Server, Connect to DB & Start Server

Now time to integrate GraphQL with backend in index.js file

const express = require('express');
                         const mongoose = require('mongoose');
                         const { ApolloServer } = require('apollo-server-express');
                         //Resolvers
                         const BookResolver = require('/src/resolvers/BookResolver');
                         const AuthorResolver = require('/src/resolvers/AuthorResolver');
                         const UserResolver = require('/src/resolvers/UserResolver'), ;
                         //Type Defs
                         const AuthorTypedef = require('/src/typesDefs/AuthorTypeDef');
                         const BookTypedef = require('/src/typesDefs/BookTypeDef');
                         const UserTypedef = require("./src/typesDefs/UserTypedef');
                         
                         // function to create graphql apollo server
                         async function startServer() {
                         const app = express();
                         const apolloServer = new ApolloServer({
                         typeDefs: [BookTypeDef, Author TypeDef, UserTypeDef],
                         resolvers: [BookResolver, AuthorResolver, UserResolver),
                         context: async ({ reg }) => {
                         },
                         });
                         // Start grapql server
                         await apolloServer.start();
                         // Apply express (app) as middleware
                         await apolloServer.applyMiddleware({ app: app });
                         // MongoDb database connection
                         await mongoose.connect('mongodb://localhost:27017/book_db', {
                         useUnifiedTopology: true,
                         useNewUrlParser: true
                         })
                         console.log("Mongodb connected ........");
                         app.listen(4000, () => {
                         console.log("Server is running on port: 4000");
                         startServer();
                         })
                         }
                         startServer()

Explanation of GraphQL Keywords

In the above code, you can see how you can configure and start GraphQL

I think you are familiar with express & mongoose, and now ApolloServer. We use three keywords here “typeDefs” & “resolvers”, the next “context” that will need to be explained.

typeDefs: Document or documents that represent your server’s GraphQL schema.

That needs to pass in typeDefs props while creating ApolloServer. A typeDefs looking like

const { gql } = require('apollo-server-express'),
                         const BookTypedef = gql`
                         # AuthorInput
                         type Author {
                         id: ID
                         authorName: String
                         description: String
                         email: String
                         }
                         # Book
                         type Book {
                         id: ID
                         title: String
                         bookescription: String
                         publishedYear: Int
                         author: Author,
                         bookImage: File
                         }
                         type Query {
                         getAllBooks: [Book]
                         getBooksByAuthor(id: ID): [Book]
                         getSingleBook(id:ID): Book
                         }
                         input BookInput {
                         title: String
                         bookdescription: String
                         publishedYear: Int
                         author: String
                         }
                         type Mutation {
                         createBook (book: BookInput): Book
                         updateBook(id: String, book: BookInput) : Book
                         deleteBook (id: String): String
                         deleteAllBook: String
                         }
                         `
                         module.exports = BookTypeDef

Explanation:

  • “Mutation”:
    • Mutation queries modify data in the data store and return a value.
  • “resolvers”:
    • A resolver is a function that’s responsible for populating the data for a single field in your schema.
  • “Query”:
    • A GraphQL query is used to read or fetch values, which means to perform the “GET” method, we can use query.
  • “Book” & “Author”:
    • “Book” & “Author” are types that contain which fields are allowed to send as a response. It is user-defined, & we need the “type” keyword to define it.
  • “BookInput”:
    • “BookInput” is an input type that contains what fields we are going to receive in the request body.
  • Note: If we declare any field as “äuthorName”: String! It indicates the required field.
  • // BookModal that defined for MongoDB Book Schema.
                             
                             const Book = require('../models/BookModal');
                             
                             const BookResolver = {
                             
                             Query: {
                             
                             getAllBooks: async (parent, args, context, info) => {
                             
                             return await Book.find().populate("author");
                             
                             },
                             
                             getSingleBook: async (parent, args, context, info) => {
                             
                             return await Book.findById(args.id).populate("author");
                             
                             }
                             
                             getBooksByAuthor: async (parent, args, context, info) => {
                             
                             let books = await Book.find({ author: args.id })
                             
                             return books;
                             
                             }
                             
                             }
                             
                             Mutation: {
                             
                             createBook: async (parent, args, context, info) => {
                             
                             const book = new Book(args.book);
                             
                             await book.save();
                             
                             return book;
                             
                             }
                             
                             updateBook: async (parent, args, context, info) => {
                             
                             const { id } = args
                             
                             const book = await Book.findByIdAndUpdate(id, args.book);
                             
                             return book;
                             
                             }
                             
                             deleteBook: async (parent, args, context, info) => {
                             
                             const { id } = args
                             
                             await Book.findByIdAndDelete(id)
                             
                             console.log("Book deleted successfully");
                             
                             return "Book deleted successfully";
                             
                             }
                             
                             deleteAllBook: async (parent, args, context, info) =>{
                             
                             await Book.deleteMany()
                             
                             return "Books deleted successfully";
                             
                             }
                             
                             }}
                             
                             module.exports = BookResolver
  • Explanation:
    • It is a resolver for “Book”, in this, we defined Query, & Mutation’s methods that were declared in typeDefs. You can understand better by looking at the above image, let’s see.
  • Mutation: {
                             
                             createBook: async (parent, args, context, info) => {
                             
                             const book = new Book(args.book);
                             
                             await book.save();
                             
                             return book;
                             
                             }
                             
                             }
  • All parameters (parent, args, context, info) are predefined & are explained very well in the doc: https://graphql.org/learn/execution/
  • The operations which were performed in the controller to insert or update data into the database, perform here in the resolver for particular operations.
    • : Hereafter save data into the database, it is returning a “book” object & “book” object may have many fields value, but because of graphQL, it will check “Book” type in typeDefs & return only those filed that will match in Book type.
  • Query: {
                             
                             getAllBooks: async (parent, args, context, info) => {
                             
                             return await Book.find().populate("author");
                             
                             }
                             
                             }
  • Here all methods that are declared in typeDefs’ Query are defined. It performs fetch operations & returns “Book” objects with only those fields which are declared in “Book” type in typeDefs.
  • “Configure GraphQL Apollo Server”:
    • : After creating typeDefs & resolver, We will create Apollo Server & start that.
  • const apolloServer = new ApolloServer({
                             
                             typeDefs: [BookTypeDef, Author TypeDef, UserTypeDef],
                             
                             resolvers: [BookResolver, AuthorResolver, UserResolver),
                             
                             context: async ({ reg }) => {
                             
                             },
                             
                             });
  • in the above image, you can see “context”. This means inside that we can verify user credential & header’s auth token before going in the resolver, & can throw Authentication error from here, and in the resolver, there is a parameter “context” that contains login user information. We can throw errors if not get user data.

Creating React Native project & Implement GraphQL (Apollo Client)

  • Step-1: Now finally, We are done with the backend all stuff
    • Create a React Native app : npx react-native init LibraryM_frontend
  • Step-2: Open App in VS code & install required npm packages
    • For Navigation, you can use the react-navigation library:
    • npm install @apollo/client graphql
      There are two libs needed to install “@apollo/client” & “graphql”.
  • Step-3: You can create a folder structure like below.

Create folder structure for React Native app (Frontend)

Create Folder Structure For React Native App

Write queries & mutations in the book.js file, that will be used to fetch & update data.

The below image represents “query” which means fetch operations.

Integrate & Configure GraphQL in React Native App (Apollo Client)

import { gql, useMutation } from '@apollo/client'
                         
                         // Queries
                         const GET_ALL_AUTHOR = gql`
                         query getAllAuthors {
                         getAllAuthors {
                         id
                         authorName
                         description
                         email
                         }
                         }
                         `;
                         
                         const GET_SINGLE_AUTHOR = gql`
                         query getSingleAuthor {
                         getSingleAuthor {
                         id
                         authorName
                         description
                         email
                         }
                         }
                         `;

The below image represents the insert operation, similarly, we can write for the update & delete.

import {gql} from '@apollo/client'
                         // Mutations
                         const ADD_NEW_AUTHOR = gql`
                         mutation createAuthor($authorName:String, $description:String, $email:String) {
                         createAuthor(author:{
                         authorName: $authorName,
                         description: $description,
                         email: $email
                         }) {
                         id
                         authorName
                         description
                         email
                         }
                         }
                         `;
                         
                         const UPDATE_AUTHOR = gql`
                         mutation updateAuthor($id: String, $authorName:String, $description:String, $email:String) {
                         updateAuthor(id:$id, author:{
                         authorName: $authorName,
                         description: $description,
                         email: $email
                         }) {
                         id
                         authorName
                         description
                         email
                         }
                         }
                         `;
                         
                         const DELETE_AUTHOR_BY_ID = gql`
                         mutation deleteAuthor($id: String) {
                         deleteAuthor(id: $id)
                         }
                         `;
                         
                         const DELETE_ALL_AUTHOR = gql`
                         mutation deleteAllAuthor {
                         deleteAllAuthors
                         }
                         `;
                         
                         export {
                         GET_ALL_AUTHOR,
                         GET_SINGLE_AUTHOR,
                         ADD_NEW_AUTHOR,
                         UPDATE_AUTHOR,
                         DELETE_AUTHOR_BY_ID,
                         DELETE_ALL_AUTHOR
                         }

Configure Apollo client in App.js file

import React from 'react';
                         import { ApolloClient, createHttpLink, InMemoryCache, ApolloProvider} from '@apollo/client';
                         import RootNavigation from './src/RootNavigation';
                         
                         //create http link based on base url
                         const httpLink = createHttpLink({
                         uri: 'http://192.168.1.34:4000/graphql',
                         });
                         
                         //Create apollo client object
                         const client = new ApolloClient({
                         link: httpLink ,
                         cache: new InMemoryCache(),
                         // credentials:'include'
                         });
                         
                         export default function App() {
                         return (
                         <ApolloProvider client={client}>
                         <RootNavigation />
                         </ApolloProvider>
                         )
                         }
  • Explanation:
    • In the above image “http://192.168.1.34” is the IP of my backend server PC & “4000” is port, “/graphql” is the default URL that is automatically added if you don’t specify in “apolloServer.applyMiddleware({})” “path” param ( It is part of backend )
  • await apolloServer.start();
                             await apolloServer.applyMiddleware({ app: app, path:"/graphql" })
  • <ApolloProvider client={client}/>: That wraps our root component, Hence all child components or screens can access the “client”‘s instance & using that we can perform operations of fetch & update.
  • import React, { useState } from 'react'
                             import { useMutation, useQuery, useApolloClient } from '@apollo/client';
                             import { View, Text, Flatlist, SafeAreaView, Alert, Image } from 'react-native'
                             import { GET_ALL BOOKS }_from '../graphQLAPI/book';
                             
                             export default function Home (props) {
                             // local states
                             const_[books, setBooks] = useState( []),
                             // get apollo client instance
                             const client = useApolloclient();
                             //fetch book data
                             const { loading, error, data } = useQuery(GET_ALL_BOOKS),
                             // delete book data
                             const [deleteBook, { data: deletedData, loading: deleteLoading, error: deleteError }] = useMutation (DELETE_BOOK_BY_ID);
                             return(
                             <SafeAreaView style={{ flex: 1, backgroundColor: "#E8F3F3"}}>
                             <FlatList
                             data={data?.getAllBooks || []} // data.getAllBooks returns all book data
                             renderItem={_renderItem}
                             keyExtractor={(item, index) => index.toString() }
                             refreshing={true}
                             />
                             </SafeAreaView>
                             )
                             }
  • “useQuery()”: Above example fetch books data from backend using “useQuery()” hook.
  • And “data.getAllBooks” contains all book data here “getAllBooks” is clear in /graphQLAPI/book.js
  • // Queries
                             const GET_ALL_AUTHOR = gql`
                             query getAllAuthors {
                             getAllAuthors {
                             id
                             authorName
                             description
                             email
                             }
                             }
                             `;
  • useMutation()” : This apollo client hook is used to perform insert, update, delete operations. The below image represents how that works
  • useMutation
  • useMutation1

I hope the above code makes it clear to understand how we can insert data using the “useMutation” hook.

Troubleshooting Common Issues

1. Identifying and resolving common React Native errors

React Native app development services may have various issues, including unexpected behavior, crashes, or unresponsive components. It is crucial to start by looking through the application’s logs and console output for error messages to address these issues. These communications frequently offer critical cues about the nature of the case. Examples of often occurring errors include syntax errors, missing dependencies, and problems with native modules.

When this occurs, checking dependencies, updating packages, and testing the application on various hardware or simulators can all help to pinpoint the problem’s fundamental cause. Additionally, using tools like React Native Debugger or Reactotron can offer deeper insights into the state and behavior of the application, assisting with troubleshooting.

2. Debugging common GraphQL and Node.js issues

Unexpected data retrieval may result from problems with GraphQL queries and Node.js server requests. One of the first steps in debugging such issues is carefully reviewing the query and mutation requests and contrasting them with the server’s schema. The schema definitions and resolvers have to match the appropriate data structure.

Utilizing tools like GraphiQL or GraphQL Playground can be very helpful in testing and troubleshooting GraphQL queries. These technologies enable a more informative and participatory method of query examination.

Additionally, monitoring server logs might help spot performance hiccups and potential faults in the Node.js backend. Monitoring the server logs can provide helpful hints for resolving problems and improving the performance of GraphQL.

3. Troubleshooting server-client communication problems

Commonly, communication issues between the React Native client and the Node.js server cause applications to misbehave. Checking the network connectivity between these two components is the first step in troubleshooting such problems. Make that the server is running and reachable from the client application

Problems with cross-origin resource sharing (CORS) might also result in barriers that prevent the client from connecting to the server. Configure the CORS settings on the server to permit the necessary origins to fix the issue.

Additionally, using network debugging tools like Charles Proxy or Wireshark to trace network requests and responses can be helpful. These technologies make it easier to identify and comprehend communication concerns, which makes it easier to address the underlying problems.

How can Bigscal help Create an Application In React Native With Node.Js Backend And GraphQL?

When you are still in confusion on how to start building an application in React Native with Node.Js backend and graphQL, then reach out to us.

Our skilled team of developers excels in building robust backends with Node.js, harnessing its scalability and speed for top-notch performance.

GraphQL integration enables efficient data fetching, eliminating over-fetching and under-fetching issues to optimize your app’s performance.

At Bigscal, we offer React Native development services covering every aspect of app development, from ideation to deployment, providing tailored end-to-end solutions that perfectly match your requirements.

Experience the remarkable potential of React Native and Node.js, combined with the flexibility of GraphQL, all skillfully brought together by Bigscal’s proficiency, making your app development journey an undeniable success.

Conclusion

GraphQL makes it easy & efficient to fetch & update data. And it also provides the benefits of graphQL features. So, start work on your app development project today.

At Bigscal Technologie, you can Hire React Native Developers & Offshore React Native Developers And Save up to 60% On Costs And Time, With No Hiring Fees.

FAQ

React Native is the front end, while Node.js powers the backend API, enabling seamless communication between the app and server.

Node.js offers high scalability, non-blocking I/O, and a vast array of libraries, making it ideal for building fast and responsive APIs.

GraphQL streamlines data fetching, reducing network overhead and enabling clients to request only the required data, improving app performance.

In most cases, yes! React Native allows reusing many React components, easing development and ensuring consistency.

React Native’s flexibility and community support make it viable for developing complex and feature-rich applications.