Mate - React Redux Material Admin Dashboard | RedQ Inc

A react-redux powered single page material admin dashboard. Used progressive web application pattern, highly optimized for your next react application.

BUILT WITH :
- Create React App [ Not ejected ]
- React
- Redux
- Redux-Saga
- Webpack
- React Router 4
- Async Loading
- Code Splitting.
- Flexbox Grid.
- Material UI
- RTL supported
- Multilingual supported [ React Intl ]
- Styled Component 
- Ion icons
- Firebase
- Auth0
- Babel, ES6 & Prettier 
- No jQuery 
- JWT Server side implementation [ Laravel, Express, Spark, Flask, Django ]

RedQ Inc

Build a React Native app with PostgreSQL and GraphQL - Part 1

Build a React Native app with PostgreSQL and GraphQL - Part 1

In this two-part series, we’ll be looking at how we can develop an application with React Native and GraphQL. To do this, we’ll be building a simple note-taking app that allows our user to add notes, view, edit and delete them.

React Native is a great option when it comes to developing mobile applications for both iOS and Android smartphones. With React Native you can write an application that works on both platforms with the only difference coming at the view level, with iOS and Android rendering differently. In this two-part series, we’ll be looking at how we can develop an application with React Native and GraphQL. To do this, we’ll be building a simple note-taking app that allows our user to add notes, view, edit and delete them.

For the first part, we’ll be building a GraphQL server with a PostgreSQL database that will serve as the backend of our application. In the second part (blog post to come later) we will build an application with React Native that will consume data from our server.

Let’s get started with our server setup. The folder structure for our project will be as shown in this repo.

In order to build our application, you will need to be familiar with:

  • NodeJS
  • Express
  • Databases
  • Mobile development
How to set up an Apollo server with Express

Our backend server will run on Node JS and Express. We’ll have a few initial dependencies to install, but first, we’ll need to initiate our app, run:

npm init

Now let us install our first set of dependencies:

npm install apollo-server apollo-server-express express graphql cors --save

One of the dependencies we have installed is apollo-server, Apollo Server is the best way to quickly build a production-ready, self-documenting API for GraphQL clients, using data from any source. While we are using it with Express, it may be used with several popular libraries such as Hapi and Koa.

Now we are all set to start creating our server. Add the following code to src/index.js.

import cors from 'cors';
import express from 'express';
import {
    ApolloServer
} from 'apollo-server-express';

const app = express();

app.use(cors());

const server = new ApolloServer({});

server.applyMiddleware({
app,
path: '/graphql'
});

app.listen({
port: 8000
}, () => {
console.log('Apollo Server on http://localhost:8000/graphql');
});

Let’s go through what we have so far, in the code above, we have initialized an Express application as well as an Apollo server instance. Using Apollo Server’s applyMiddleware() method, you can opt-in any middleware, which in our case is the Express app. Also, you can specify the path for your GraphQL API endpoint.

You may also note we applied cors to our Express application, this is to allow external domains to access our application.

Our next step would be to define our schema and resolvers for the Apollo Server instance. But first, let’s cover schema and resolvers.

Schema

The GraphQL schema provided to the Apollo Server is all of the available data for reading and writing data via GraphQL. The schema contains type definitions from a mandatory top-level Query type that allows reading of data followed by field and nested fields. These are defined using the GraphQL Schema Language and allows us to talk about GraphQL schemas in a language-agnostic way.

Here’s what’s in our schema/notes.js:

import {
gql
} from 'apollo-server-express';

export default gql `
extend type Query {
notes: [Note!]
note(id: ID!): Note!
}

type Note {
id: ID!
text: String!
}
`;

Let’s take a look at our schema definition for some notable terms we need to be aware of. We have already covered the Query type, but let’s look at the rest:

  • notes is defined as [Note!] which represents an array of Note objects. The exclamation mark means it is non-nullable, this means you can always expect an array (with zero or more items) when you query the notes field
  • Each Note object contains an id field defined as ID . The ID scalar type represents a unique identifier, often used to re-fetch an object or as the key for a cache. It is serialized the same way a String is serialized. However, defining it as an ID signifies that it is not intended to be human‐readable
  • The Note object also has a text field defined as String which is one of the built-in scalar types that is a sequence of UTF-8 characters
  • You will also notice the note field is provided with id options in the form of (id: ID!). This allows for the use of GraphQL arguments to refine queries. This allows us to fetch a single note by providing it’s ID in our query. The argument is also non-nullable as it must be provided when fetching a single note.

The schema above shall be placed in src/schema/notes.js. We can then have a index.js file inside the src/schema directory with the following code:

import { gql } from "apollo-server-express";

import noteSchema from "./notes";

const linkSchema = gql`
  type Query {
    _: Boolean
  }

  type Mutation {
    _: Boolean
  }

  type Subscription {
    _: Boolean
  }
`;

export default [linkSchema, noteSchema];

Resolvers

Resolvers are responsible for manipulating and returning data, think of them as the query handlers. Each top-level query in the Query type has a resolver but we’ll make our own per field. The resolvers are grouped in a JavaScript object, often called a resolver map.

Let’s create a notes.js file inside src/resolvers and add the following code to it:

export default {
Query: {
notes: (parent, args, {
models
}) => {
return Object.values(models.notes)
},
note: (parent, {
id
}, {
models
}) => {
return models.notes[id]
}
}
}

The above resolvers allow us to query either individual notes using the note field and provide an id argument or an array of notes using the notes field. We’ll clean up our resolvers once we link our app to the database using sequelize and add Mutations which will allow us to carry out operations other than reading on our data. For now, these resolve dummy data that we’ll have in src/models/index.js which contains the following code:

let notes = {
1: {
id: '1',
text: 'Hello World',
},
2: {
id: '2',
text: 'By World',
},
};

export default {
notes
};

Now that we have the framework set up for how our data will be stored let’s look at how data manipulation will be done using queries and mutations.

Queries and mutations

Queries and mutations in GraphQL allow us to access and manipulate data on a GraphQL server. Queries are in charge of read operations whereas mutations are in charge of create, update and delete operations.

To create our queries and mutations, we must first define them in our schema. Let’s edit src/schema/notes.js as follows:

import {
gql
} from 'apollo-server-express';

export default gql `
extend type Query {
notes: [Note!]
note(id: ID!): Note!
}

extend type Mutation {
createNewNote(text: String!): Note!
deleteNote(id: ID!): Boolean!
updateNote(id: ID!, text: String!): Note!
}

type Note {
id: ID!
text: String!
}
`;

Queries have already been defined earlier so our new addition is the Mutationtype. From the types defined, you can get an idea of what the returned data will look like. For instance, createNewNote takes a text argument that is a string and generates and returns a Note object, updateNote is similar but it also takes the id so that it can find the note to be updated. Meanwhile, deleteNote takes an idboolean that is used to identify the target note and returns a boolean indicating whether the note has been deleted successfully or not.

This is how you can test your queries. Type the following code in your graphql playground:

Get all notes

Fetches and returns all notes saved.

query {
notes {
id
text
}
}

Next hit the Execute Query button and you should be able to see the following result:

Result

{
"data": {
"notes": [
{
"id": "1",
"text": "Hello World"
},
{
"id": "3",
"text": "By World"
}
]
}
}

Get note by id

This returns a piece of the data matching the given argument id

query{
note(id: "1") {
id
text
}
}

Result

{
"data": {
"note": {
"id": "1",
"text": "Hello World"
}
}

Next, we’ll need to write a Mutation resolver. Let’s editsrc/resolvers/notes.js

like this:

import uuidv4 from 'uuid/v4';

export default {
Query: {
notes: (parent, args, {
models
}) => {
return Object.values(models.notes)
},
note: (parent, {
id
}, {
models
}) => {
return models.notes[id]
}
},
Mutation: {
createNewNote: (parent, {
text
}, {
models
}) => {
const id = uuidv4();
const newNote = {
id,
text
}
models.notes[id] = newNote;
return newNote;
},

    deleteNote: (parent, {
        id
    }, {
        models
    }) => {
        const {
            [id]: note, ...otherNotes
        } = models.notes
        if (!note) {
            return false
        }
        models.notes = otherNotes
        return true
    },

}

For the createNewNote Mutation we are generating the unique id using the uuid/v4 library so we’ll need to install it by running:

npm install uuid/v4 --save

The resolver takes a text argument, generates a unique id and uses them to create a Note object which is then appended to the list of notes. It then returns the new note that has been created.

The deleteNote Mutation takes an id argument, finds a note and creates a new notes object without the note to be deleted and replaces the old notes object with the new one. It returns false if the note is not found and true when the note is found and deleted.

The updateNote Mutation takes the id and text as arguments and updates the Note in the notes object accordingly, returning the updated note at the end.

We can now access these endpoints through the GraphQL playground when we run our application by running npm start and going to localhost:3000/graphql on the browser. You can then try out these actions:

Create a new note

Takes a text argument and creates and returns a note.

mutation {
createNewNote( text: "Hello GraphQl") {
id
text
}
}

Result

{
"data": {
"createNewNote": {
"id": "3",
"text": "Hello GraphQl"
}
}
}

Update note

Takes text and id arguments and updates and returns a note.

mutation {
updateNote(id:3, text:"Graphql is awesome") {
id
text
}
}

Result

{
"data": {
"updateNote": {
"id": "4",
"text": "Graphql is awesome"
}
}
}

Delete note

Takes an id argument and deletes the matching note.

mutation {
deleteNote(id:5)
}
Adding PostgreSQL with Sequelize

We have most of our app ready to go so the next thing we need to look at is how we can save our data to a database. Our database will be PostgreSQL so go ahead and install it from their site then start it.

After that, create a database called mynotes. To do this you can run the command psql in your terminal to open up the PosgreSQL CLI. Once open run:

CREATE DATABASE mynotes;
CREATE USER postgres;
GRANT ALL PRIVILEGES ON DATABASE members TO postgres;

Next you’ll want to add PostgreSQL for Node.js and Sequelize (ORM) to your project. Run:

npm install pg sequelize --save

The next step is to update our models to prepare to link to the database as shown below. The model defines the shape of each piece of data as it will be stored in the database:

const note = (sequelize, DataTypes) => {
const Note = sequelize.define("note", {
text: DataTypes.STRING
});
return Note;
};

export default note;

Next, connect to your database from within your application in the src/models/index.js file:

import Sequelize from "sequelize";

const sequelize = new Sequelize(
process.env.DATABASE,
process.env.DATABASE_USER,
process.env.DATABASE_PASSWORD,
{
dialect: "postgres"
}
);

const models = {
Note: sequelize.import("./notes")
};

Object.keys(models).forEach((key) => {
if ("associate" in models[key]) {
models[key].associate(models);
}
});

export { sequelize };
export default models;

You’ll need to define the database name, a database super-user, and the user’s password. You may also want to define a database dialect because Sequelize supports other databases as well.

In the same file, you can physically associate all your models with each other if you have multiple models (hence the foreEach loop above) to expose them to your application as data access layer (models) for the database. In our case, we only have one model but this is still good to know.

Now let’s create a .env file at the root directory of the project to hold some critical data as environment variables. The database credentials (database name, database super user name, database super-user password) can be stored as environment variables along with the port on which we wish to run our server.

In the .env file add the following variables or change them to your liking:

PORT=3000
DATABASE=mynotes
DATABASE_USER=postgres
DATABASE_PASSWORD=postgres

Next, let’s update src/index.js to get our databases synchronized when our application is started. Make the following changes:

...
import 'dotenv/config';
import models, {
sequelize
} from './models';
...

sequelize.sync().then(async () => {
app.listen({
port: 8000 // you could change this to process.env.PORT if you wish
}, () => {
console.log('Apollo Server on http://localhost:8000/graphql');
});
});

We’ve now linked our application to the database so what we need to do next is replace the logic in our resolvers.

How to connect resolvers to the database

We had dummy data before but with Sequelize we can now allow us to sync our data with our database, allowing for data persistence. To make this happen, we need to update our resolver in src/resolvers/notes.js to integrate the Sequelize API.

export default {
Query: {
notes: async (parent, args, { models }) => {
return await models.Note.findAll();
},

note: async (parent, { id }, { models }) => {
  return await models.Note.findByPk(id);
}

},
Mutation: {
createNewNote: async (parent, { text }, { models }) => {
return await models.Note.create({
text
});
},

deleteNote: async (parent, { id }, { models }) => {
  return await models.Note.destroy({
    where: {
      id
    }
  });
},
updateNote: async (parent, { id, text }, { models }) => {
  await models.Note.update(
    {
      text
    },
    {
      where: {
        id: id
      }
    }
  );
  const updatedNote = await models.Note.findByPk(id, {
    include
  });
  return updatedNote;
}

}
};

You will notice we no longer need uuid/v4 as Sequelize automatically handles the assignment of ids in our database. The findAll() and findByPk() are commonly used Sequelize methods for database operations, findAll() returns all entries in a certain table whereas findPk() identifies and returns entries that fit a certain criterion such as a matching id in our case.

Other Sequelize methods we make use of include update() and destroy() to update and delete records respectively.

Along with these, we use async/await to implement promise-based asynchronous Javascript requests to our database.

Conclusion

Great! We are all ready to go, the next step is to integrate our GraphQL backend with our front-end app, which we’ll build for mobile in part two of this tutorial.

Thanks For Visiting, Keep Visiting. If you liked this post, share it with all of your programming buddies!


Originally published on blog.logrocket.com

ReactJS Development Company in Canada| Hire React JS Developers

a successful and trustworthy ReactJS development company in Ontario, Canada with presence in India. Hire our professional React JS developer who will guarantee you the custom ReactJS development and create bug-free, creative, seamless and interactive user interface apps. Get our services at the most competitive prices.

Top React Native Developers in the USA

For most mobile app development company it is incredibly important to maintain shorter development cycles while not compromising on feature set or cross-platform native performance. Often developers need to ensure any one if these at the expense of others. React Native is one of the development languages that ensure fast-paced development by reusing codes while boosting the apps with native capabilities.

Website: Top React Native Developers in USA