How to build a React note-taking App with GraphQL

GraphQL is an open-source query and manipulation language for APIs, and a runtime for fulfilling those queries with your existing data. It enables front-end developers to write queries that return the exact data you want. It uses a syntax that describes how to ask for data and is generally used to load data from a server to a client.

GraphQL is language-agnostic as it can work with any server-side language. GraphQL aims to speed up development, improve the developer experience and offer better tooling. It’s often seen as an alternative to REST when building web applications.

How is GraphQL different from REST?

One of the major advantages GraphQL has over REST is that it allows you to get many resources in a single request. GraphQL queries access not just the properties of one resource but also smoothly follow references between them.

While typical REST APIs require loading from multiple URLs, GraphQL APIs get all the data your app needs in a single request.

In a bid to understand GraphQL on both the server and the frontend, you’ll build a note-taking app. The app would be able to do the following:

  • List all notes from the server
  • Add a new note by passing a title and a content to the server.
  • Edit a note by passing a title and content to the server
  • Delete a note from the server.

Prerequisites

  • Node.js and npm installed on your local machine. You can install both of these from the Node.js website here.
  • MongoDB installed on your local computer.
  • A text editor installed, such as Visual Studio Code, Atom, or Sublime Text.
  • Some experience with the React library.
  • Some working knowledge of Node.js
  • Node (8)
  • npm (5.2.0)

Installing Project Dependencies

To get started with your note-taking app, you’ll build your Node.js and GraphQL server by installing the dependencies for your project to your local development environment.

For this tutorial, you’ll create a project folder for your application named notetaking-api. Open your terminal and set up a project folder for your app to live in:

mkdir notetaking-api

Now navigate into your new project folder:

cd notetaking-api

First of all, you’ll need to create a package.json file to install all the required dependencies. The package.json file is needed to manage dependencies that might be needed in the app and also for writing scripts that help with build and test processes. Run the following command to generate a package.json file:

npm init --yes

It automatically creates a package.json file. With that done, let’s add the required dependencies with the following command:

npm install --save express graphql express-graphql graphql-tools mongoose nodemon
  • Express is a fast and minimal web framework for Node.js.
  • [graphql](https://github.com/graphql/graphql-js) is the JavaScript reference implementation for GraphQL.
  • [express-graphql](https://github.com/graphql/express-graphql) is a package that allows you to create a GraphQL HTTP server with Express.
  • [graphql-tools](https://github.com/apollographql/graphql-tools) is a package that allows us to build, mock, and stitch a GraphQL schema using the schema language.
  • [mongoose](https://github.com/Automattic/mongoose/) is an object modeling (ODM) tool that we’ll use to connect to MongoDB.
  • [nodemon](https://github.com/remy/nodemon) is a tool that listens for file changes in a Node app that automatically restarts the server.

Next, install the following dev dependencies:

npm install — save-dev babel-cli babel-preset-env babel-preset-stage-0

You’ll be writing ES6 code in this tutorial, therefore, you’ll need Babel to transpile the Node app. ECMAScript, or ES6 is a standardized name for JavaScript and it signifies the 6th version. It adds features like constants, block-scoped variables and functions, arrow functions, string templating and many more.

Now that the dependencies are installed, you can go ahead to create the express server for the Node application.

Creating the Express Server

In this section, you’ll create the foundation for the note-taking API, a minimal express server that listens on a port.

The first thing to do is to add a new script titled "start" to the package.json file which will be responsible for running the app. Next, open your package.json file in your text editor.

You can add the "start" script under the existing "test" script:

...
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon ./index.js --exec babel-node -e js"
  }
...

nodemon is used to start (and also listen for changes) the app which is at the entry point of the index.js file and the babel flag is added so as to transpile ES6 code.

To transpile the code, babel needs a config file. The file can be created by running the command below in the notetaking-api folder. The command below creates a .babelrc which will contain babel configurations.

touch .babelrc

Next, open the config file in your text editor and edit with the code below.

{
  "presets": ["env", "stage-0"]
}

Babel will look for a .babelrc in the current directory of the file being transpiled. In the code block above, we added a preset array which is essentially a configuration of how babel should transpile JavaScript code.

Let’s get things rolling by creating the Express server for the note-taking API. Create an index.js file in the notetaking-api folder, open the newly created file and edit with the code below:

import express from "express";const app = express();
const PORT = 4300;app.get("/", (req, res) => {
  res.json({
    message: "Notetaking API v1"
  });
});
app.listen(PORT, () => {
  console.log(`Server is listening on PORT ${PORT}`);
});

In the code block above, this app starts a server and listens on the port 4300 for connections. The express module is first imported from the express package. Next, the module function is assigned to a variable called app, and a variable called PORT is created which holds the port number in which the server will live .

Next, you’ll handle a GET request to our server using the .get() function. The .get() function takes two main parameters. The first is the URL for this function to act upon. In this case, we are targeting '/', which is the root of our API; in this case, localhost:4300.

Finally, the app is started using the .listen() function, which also tells the app which port to listen on by using the PORT variable created earlier.

Save the changes you just made to the index.js file and run the command below in the notetaking-api folder to run the app.

npm start

The express server will now be running on the port 4300 and you should see a JSON output when you navigate to http://localhost:4300/.

Connecting the MongoDB Server to Mongoose

In this step, you’ll see how to connect the already existing Express server to MongoDB via mongoose.

For the note-taking API, you’ll need to store the notes somewhere, this is where MongoDB comes in. MongoDB is a document-oriented, NoSQL database program. It enables storing data in JSON-like documents that can vary in structure.

Moongoose, meanwhile, is an Object Data Modeling (ODM) library for MongoDB and Node.js. It manages relationships between data, provides schema validation, and is used to translate between objects in code and the representation of those objects in MongoDB.

In this step, you’ll create a MongoDB database and connect it to the API using Mongoose.

import express from "express";
import mongoose from "mongoose";mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost/notetaking_db", {
  useNewUrlParser: true,
  useUnifiedTopology: true
});const app = express();
const PORT = 4300;app.get("/", (req, res) => {
  res.json({
    message: "Notetaking API v1"
  });
});
app.listen(PORT, () => {
  console.log(`Server is listening on PORT ${PORT}`);
});

You first import the mongoose package and set it to connect to a MongoDB via a database called notetaking_db.

Since you’ll be using Mongoose, you can go ahead to create your model. Models are constructors that are defined manually. They allow you to access data from MongoDB in an object-oriented fashion. The first step to creating a model is defining the schema for it. In this case, the schema for the API will be created.

Therefore, create a folder named models in the notetaking-api folder,

mkdir models

And navigate into it:

cd models

Then in models, create a note.js file:

touch note.js

Now add the following content to note.js to define the schema:

import  mongoose from 'mongoose';
const Schema = mongoose.Schema;const NoteSchema = new Schema({
    title : {
        type: String,
        required: true
    },
    content: {
        type: String,
        required: true
    },
    date: {
        type: Date,
        default: Date.now
    }
});export default  mongoose.model('note', NoteSchema);

Let’s go back to the specs of the note-taking API as it’s going to help understand the schema above:

  • List all notes from the server
  • Add a new note by passing a title and a content to the server.
  • Edit a note by passing a title and content to the server
  • Delete a note from the server.

From the specs above, a note entry needs to have both a title and its content and that’s what was in the model above. The title schema accepts a string and has its required option set to true, same as the content schema. The date schema automatically logs the current date. MongoDB automatically creates an id so we need not worry about indexing.

In the section above, you created a MongoDB database and connected it to the Node.js app using Mongoose. You also created the necessary schema needed for the API. In the next section, you’ll see how to set up the GraphQL server.

Setting up the GraphQL Server

In this section, you’ll set up the GraphQL server so we can begin sending and getting data from the database. This will be done by installing some GraphQL dependencies and integrating them into the existing Node.js app.

Let’s get started by making some modifications to the index.js file. Open the index.js file and edit with the following code.

import express from "express";
import graphlHTTP from "express-graphql";
import mongoose from "mongoose";
import schema from "./schema";mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost/notetaking_db", {
  useNewUrlParser: true,
  useUnifiedTopology: true
});const app = express();
const PORT = 4300;app.get("/", (req, res) => {
  res.json({
    message: "Notetaking API v1"
  });
});
app.use(
  "/graphql",
  graphlHTTP({
    schema: schema,
    graphiql: true
  })
);
app.listen(PORT, () => {
  console.log(`Server is listening on PORT ${PORT}`);
});

In the code block above, express-graphql is used to create a graphql server app based on a schema and resolver functions. Therefore, when you send a GraphQL query or mutation request, the middleware will be called and it runs the appropriate GraphQL operation.

A GraphQL schema is at the center of any GraphQL server as it helps describes the functionality available to the clients that connect to it. GraphQL queries are used by the client to request the data it needs from the server while a GraphQL mutation is a way of creating, updating and deleting existing data.

The graphiql option (which is set to true) in the graphqlHTTP middleware indicates that we’d like to make use of the web client which features a graphical user interface, GraphiQL (pronounced “Graphical”).

GraphiQL is the GraphQL integrated development environment (IDE). It is a tool that helps to query and mutate GraphQL data cleanly and easily. It has features like syntax highlighting, Intelligent type ahead of fields, arguments, types, real-time error highlighting and reporting an automatic query completion.

As seen in the notetaking-api/index.js file, The graphql endpoint requires a schema file though, which will be created below. Mongoose schemas are used to define the structure of the MongoDB document.

Creating a schema essentially consists of three things:

  • Referencing mongoose.
  • Defining the model.
  • Exporting the model.

Therefore, create a file named schema.js in the notetaking-api folder. The schema.js file is used to create the schema needed for the GraphQL server.

Open the newly created schema.js file and add the following code.

import { makeExecutableSchema } from 'graphql-tools';
import { resolvers } from './resolvers';const typeDefs = `
 type Note {
  _id: ID!
  title: String!,
  date: Date,
  content: String!
 }scalar Datetype Query {
  allNotes: [Note]
 }`;const schema = makeExecutableSchema({
    typeDefs,
    resolvers
});export default schema;

In the code block above, we created the GraphQL schema and defined our type definitions. GraphQL implements a human-readable schema syntax known as its Schema Definition Language, or “SDL”. The SDL is used to express the types available within a schema and how those types relate to each other.

The basic components of a schema are object types that represent an object you can fetch from the DB and the kind of fields to expect.

As seen in the code block above, SDL definition for a note entry into the DB is as follows:

type Note {
    _id: ID!
    title: String!,
    date: Date,
    content: String!
}scalar Datetype Query {
   allNotes: [Note]
}

The type Note declaration is a GraphQL Object Type, meaning it’s a type with some fields. It also defines the structure of a note model in the application.

_id, title, date , and content are fields in the Note type. ID and String are built in scalar types that resolve to a single scalar type and appending an exclamation mark ! means the field is non-nullable, meaning that the GraphQL service promises to always give you a value when you query this field.

A root Query type is also defined and it works when you try to fetch all the notes. It will run the allNotes resolver against this Query.

These are some of the default scalar types inbuilt with GraphQL:

  • Int: A signed 32‐bit integer.
  • Float: A signed double-precision floating-point value.
  • String: A UTF‐8 character sequence.
  • Boolean: true or false.
  • ID: The ID scalar type represents a unique identifier, often used to refetch an object or as the key for a cache.

You’ll notice the Date type is missing. That’s because GraphQL doesn’t ship with it as a default scalar type however that can be fixed with the line of code below, which is what we did in schema up there.

scalar Date

The schema is created using the makeExecutableSchema function which also expects a resolver. Resolvers are the actual implementation of the schema we defined up there.

You can now create the resolvers.js file as referenced in the code above where we imported the resolvers function into the schema.js file. The resolvers.js file is used to create functions that will be used to either query some data or modify some data.

Therefore, create a file named resolvers.js in the notetaking-api folder. Open resolvers.js file and add the code below.

import Note from './models/note';
export const resolvers = {
    Query : {
       async allNotes(){
           return await Note.find();
       }
    }
};

In the schema above, you created a root Query that returned all the notes. Ordinarily, that won’t work the way it is, you’d need to hook it up to MongoDB and resolvers help with that.

When you try to execute the allNotes query, it will run the Query resolver and find all the notes from the MongoDB database.

With all of that done, let’s test what we have so far and try sending a query to GraphQL. We’ll be sending the query below in the GraphiQL interface.

{
    allNotes {
        _id
        title
        content
        date
    }
}

To do that, run the app by using npm start and navigate to the GraphQL web client (GraphiQL) via this URL http://localhost:4300/graphql. You can then run the allNotes query as seen above.

Copy the code above and paste in the left pane of the GraphiQL interface, then click on the play button.

The expected output on the right pane should be an empty array, rightly so because we haven’t added a note entry to the database yet.

How to build a React note-taking app with GraphQL

In this step, the GraphQL server was successfully set up. In addition to that, the GraphQL schema for the API was created as well as the necessary resolver functions that help to either read data from the server.

Modifying Notes in the Database

In this section, you’ll implement the functionality to add, retrieve, update, and delete notes in your database. You’ll achieve this by creating resolver functions to make queries or mutations to the GraphQL server.

To add notes to the database, you’ll need to create a mutation in the resolvers.js file. The mutation will help to add a new record in MongoDB. Mutations are a way of modifying data in GraphQL and they work just like a query.

Open the resolvers.js file and edit with the code below.

import Note from "./models/note";
export const resolvers = {
  Query: {
    async allNotes() {
      return await Note.find();
    }
  },
  Mutation: {
    async createNote(root, { input }) {
      return await Note.create(input);
    }
  }
};

We’ll also need to make the appropriate changes in the schema.js file.

import { makeExecutableSchema } from "graphql-tools";
import { resolvers } from "./resolvers";const typeDefs = `
 type Note {
  _id: ID!
  title: String!,
  date: Date,
  content: String!
 }scalar Datetype Query {
  allNotes: [Note]
 }input NoteInput {
  title: String!
  content: String!
 }type Mutation {
  createNote(input: NoteInput) : Note
 }`;const schema = makeExecutableSchema({
  typeDefs,
  resolvers
});export default schema;

In the code block above, we defined a type, Mutation, and assigned it to the createNote resolver we wrote above. We also added a new input type which is NoteInput. You need to pass the input argument while sending the createNote mutation. The return type of this mutation is Note.

With that done, let’s try adding a Note by running a mutation to the database via GraphiQL. Run the mutation below in the GraphiQL interface.

If the app is not running you can run the command below and go ahead to navigate to localhost:4300/graphql in your browser.

mutation {
  createNote(input: {
    title: "My First note",
    content: "Here's the content in it",
  })
  {
    _id
    title
    content
    date
  }
}

How to build a React note-taking app with GraphQL

Next thing to do is to get a single note from the database. To get a single note from the database, we’ll need to create a new getNote type in schema.js file. The idea is to be able to get a note by its id.

import { makeExecutableSchema } from 'graphql-tools';
import { resolvers } from './resolvers';const typeDefs = `type Note {
  _id: ID!
  title: String!,
  date: Date,
  content: String!
 }scalar Datetype Query {
  getNote(_id: ID!): Note
  allNotes: [Note]
 }input NoteInput {
  title: String!
  content: String!
 }type Mutation {
  createNote(input: NoteInput) : Note
 }
`;const schema = makeExecutableSchema({
    typeDefs,
    resolvers
});export default schema;

The getNote type also accepts an id parameter, and the return type of the getNote is Note. Next thing to do is to create the resolver for the getNote query. Open up the resolvers.js file and edit with the code below.

import Note from './models/note';
export  const resolvers = {
    Query : {
       async getNote(root, {_id}){
           return await Note.findById(_id);
       },
       async allNotes(){
           return await Note.find();
        }
    },
    Mutation: {
        async createNote(root, {input}){
           return await Note.create(input);
        }
    }
};

In the code block above, we added a getNote resolver that uses mongoose’s findById function to find a note entry by its ID. Let’s see this in action by running the query below in the GraphiQL interface. You can use the id of the note created earlier above to search.

{
  getNote(_id: "5d8ab091330c4b44c8a24a6e") {
    _id
    title
    content
    date
  }
}

Note: Please replace the ID above (5d8ab091330c4b44c8a24a6e) with the actual ID returned from your GraphiQL
How to build a React note-taking app with GraphQL

Next, we’ll see how to update notes in the database. To update a note’s entry in the DB, an updateNote mutation has to be created in the schema.js file.

import { makeExecutableSchema } from 'graphql-tools';
import { resolvers } from './resolvers';const typeDefs = `
 type Note {
  _id: ID!
  title: String!,
  date: Date,
  content: String!
 }scalar Datetype Query {
  getNote(_id: ID!): Note
  allNotes: [Note]
 }input NoteInput {
  title: String!
  content: String!
 }input NoteUpdateInput {
   title: String
   content: String
}type Mutation {
  createNote(input: NoteInput) : Note
  updateNote(_id: ID!, input: NoteUpdateInput): Note
}
`;const schema = makeExecutableSchema({
    typeDefs,
    resolvers
});export default schema;

A new mutation is created, updateNote, it accepts a parameter of the id and the NoteUodateInput which contains the updated data (title or content) that needs to be updated.

Let’s create the resolver for the updateNote mutation. Open up the resolvers.js file and edit with the code below.

import Note from './models/note';
export  const resolvers = {
    Query : {
       async getNote(root, {_id}){
           return await Note.findById(_id);
       },
       async allNotes(){
           return await Note.find();
        }
    },
    Mutation: {
        async createNote(root, {input}){
           return await Note.create(input);
        },
        async updateNote(root, {_id, input}){
            return await Note.findOneAndUpdate({_id},input,{new: true})
        }
    }
};

In the code block above, the updateNote function uses the findOneAndUpdate function to update the particular note’s entry in the DB. As the name suggests, it finds that particular id in the DB and updates it.

We can test updating a note by running the mutation below in the GraphiQL interface.

mutation {
  updateNote(_id: "5ba70100f24d5027d7394d68", input: {
    title: "My First note",
    content:"Here's content in it"
  })
  {
    title
    content
  }
}

Note: Please replace the ID above (5ba70100f24d5027d7394d68) with the actual ID returned from your GraphiQL

How to build a React note-taking app with GraphQL

Next, we’ll see how to delete notes in the database. To delete notes in the DB, the process is similar to the ones above. You’d first need to create a deleteNote mutation in the schema.js file and then create a resolver for it in the resolvers.js file.

import { makeExecutableSchema } from 'graphql-tools';
import { resolvers } from './resolvers';const typeDefs = `type Note {
  _id: ID!
  title: String!,
  date: Date,
  content: String!
 }scalar Datetype Query {
  getNote(_id: ID!): Note
  allNotes: [Note]
 }input NoteInput {
  title: String!
  content: String!
 }type Mutation {
  createNote(input: NoteInput) : Note
  updateNote(_id: ID!, input: NoteInput): Note
  deleteNote(_id: ID!) : Note
 }
`;const schema = makeExecutableSchema({
    typeDefs,
    resolvers
});export default schema;

The deleteNote mutation accepts a parameter of id which will be used to identify the particular note to be removed from the database. Let’s create the appropriate resolver for the newly created mutation.

import Note from './models/note';
export  const resolvers = {
    Query : {
       async getNote(root, {_id}){
           return await Note.findById(_id);
       },
       async allNotes(){
           return await Note.find();
        }
    },
    Mutation: {
        async createNote(root, {input}){
           return await Note.create(input);
        },
        async updateNote(root, {_id, input}){
            return await Note.findOneAndUpdate({_id},input,{new: true})
        },
        async deleteNote(root, {_id}){
            return await Note.findOneAndRemove({_id});
        }
    }
};

In the code block above, the deleteNote mutation finds the note by its id and then uses the findOneAndRemove function to remove from the database.

You can test deleting a note by running the mutation below in the GraphiQL interface.

mutation {
  deleteNote(_id: "5ba70100f24d5027d7394d68")
  {
    title
    content
  }
}

Note: Please replace the ID above (5ba70100f24d5027d7394d68) with the actual ID returned from your GraphiQL

How to build a React note-taking app with GraphQL

You’ve now successfully created your GraphQL API server. It’s a minimal server that does the required CRUD operations. In the next part of this tutorial, you’ll set up your React application that will interface with the GraphQL server.

Therefore you’ll need to build the UI needed to add, edit and delete notes.

You’ll also install all the necessary dependencies needed to build the app’s UI.

You’ll be using the create-react-app CLI tool to build the React app. It allows you to create React apps with no need for any build configuration.

Create a React app by running the command below in your terminal. This creates a folder named notetaking-ui in your directory.

You’ll also install all the necessary dependencies needed to build the app’s UI.

You’ll be using the create-react-app CLI tool to build the React app. It allows you to create React apps with no need for any build configuration.
Create a React app by running the command below in your terminal. This creates a folder named notetaking-ui in your directory.

npx create-react-app notetaking-ui

When the installation is done, you will have a working React app in the notetaking-ui folder. Navigate into the folder and run the yarn start command to start the app in development mode.

You will be building a minimal React app, therefore, the following views are needed for the React app:

  • A view to see all the notes listed.
  • A view to edit notes.
  • A view to add notes.

To that end, create the following files in the src folder, AllNotes.js, EditNote.js, NewNote.js. We’ll edit them later on.

Now, you’ll install the required dependencies for building the UI for your note-taking app.

yarn add react-router-dom

This command installs the react-router package which is a great library for handling routing in React apps. We’ll also be making use of Bulma, a CSS framework, to help with styling the React app. Add the line of code below to the head tag in the public/index.html file to add the Bulma framework to the app.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css">

To set up the routes for the React app, you’ll need to make use of react-router to define the routes. Open up the App.js file and edit with the code below:

import React, { Component } from 'react';
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'
import './App.css';
import AllNotes from './src/AllNotes'
import NewNote from './src/NewNote'
import EditNote from './src/EditNote'class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <nav className="navbar App-header" role="navigation" aria-label="main navigation">
            <div className="navbar-brand">
              <Link to="/" className="navbar-item">
                NotesQL
              </Link>
            </div><div className="navbar-end">
              <Link to="/" className="navbar-item">
                All Notes
              </Link><Link to="/newnote" className="navbar-item">
                New Note
              </Link>
            </div>
          </nav><Route exact path="/" component={AllNotes}/>
          <Route path="/newnote" component={NewNote}/>
          <Route path="/note/:id" component={EditNote}/>
        </div>
      </Router>
    );
  }
}export default App;

In the code block above, all the components needed for react-router are imported, as well as the components for the views created above.

In the render function, the whole layout is wrapped in the <Router> component. This helps by creating a history object to keep track of the location. Therefore, when there’s a location change, the app will be r-rendered. The Link component is used to navigate through the different routes.

Finally, the code block below is where the actual routes are defined:

The / route is the homepage of the app and will always point to the AllNotes component which displays all the notes, the /newnote route is pointed to the NewNote component which contains the view to add a new note and the /note/:id route is pointed to the EditNote component which contains the view needed to edit a note. The id bit is what will be used to fetch that particular note’s detail from the database.

Creating the React App views

In this step, we’ll create the views needed for the note-taking app. In the previous step, we used the create-react-app CLI to create a functional React application. As a reminder, the views to be created are:

  • View all existing notes
  • Add a new note
  • Edit an existing note

Therefore, let’s start with the view for all notes. Open up the previously created AllNotes.js file and add the code below to the file.

import React from "react";
import { Link } from "react-router-dom";const AllNotes = () => {
  let data = [1, 2, 3, 4, 5];
  return (
    <div className="container m-t-20">
      <h1 className="page-title">All Notes</h1><div className="allnotes-page">
        <div className="columns is-multiline">
          {data.length > 0
            ? data.map((item, i) => (
                <div className="column is-one-third" key={i}>
                  <div className="card">
                    <header className="card-header">
                      <p className="card-header-title">Component</p>
                    </header>
                    <div className="card-content">
                      <div className="content">
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                        Phasellus nec iaculis mauris. Lorem ipsum dolor sit
                        amet.
                        <br />
                      </div>
                    </div>
                    <footer className="card-footer">
                      <Link to={`note/${i}`} className="card-footer-item">
                        Edit
                      </Link>
                      <a href="#" className="card-footer-item">
                        Delete
                      </a>
                    </footer>
                  </div>
                </div>
              ))
            : "No Notes yet"}
        </div>
      </div>
    </div>
  );
}export default AllNotes;

In the code block above, we’re using the Cards component from Bulma as the layout for displaying the notes. The Card component is an all-around flexible and composable component that’s used to display information in a concise manner.

Note that we’re iterating through the data array as an example, ideally, it would be the results from the database.

We’re also doing a check in the render function to check if there are available data. If there is, we display accordingly and if not a message of “No Notes yet” is displayed.

Next, you’re going to add some custom CSS for the components created above, so go ahead to update the stylesheets accordingly.

Edit the src/App.css file with the code below.

.App-header {
  background-color: #222;
  color: white;
}
​
.navbar-item {
  color: white;
}
​
.App-title {
  font-size: 1.5em;
}
​
.App-intro {
  font-size: large;
}
​
.m-t-20 {
  margin-top: 20px;
}
​
.card {
  box-shadow: 0 1px 5px 1px rgba(0, 0, 0, 0.1);
}
​
.page-title {
  font-size: 2rem;
  margin-bottom: 20px;
}
​
.newnote-page {
  height: calc(100vh - 52px);
  width: 60%;
}
​
.field:not(:last-child) {
  margin-bottom: 2.75rem;
}
​
.card button {
  border: none;
  color: #3273dc;
  cursor: pointer;
  text-decoration: none;
  font-size: 16px;
}
.card button:hover {
  color: #363636;
}

How to build a React note-taking app with GraphQL

Next, let’s create the view for adding a new note. Open up the NewNote.js file and add the code below to the file.

import React from "react";
const NewNote = () => {
  return (
    <div className="container m-t-20">
      <h1 className="page-title">New Note</h1>
​
      <div className="newnote-page m-t-20">
        <form>
          <div className="field">
            <label className="label">Note Title</label>
            <div className="control">
              <input className="input" type="text" placeholder="Note Title" />
            </div>
          </div>
​
          <div class="field">
            <label class="label">Note Content</label>
            <div class="control">
              <textarea class="textarea" rows="10" placeholder="Note Content here..."></textarea>
            </div>
          </div>
​
​
          <div class="field">
            <div class="control">
              <button class="button is-link">Submit</button>
            </div>
          </div>
​
        </form>
      </div>
    </div>
  )
}
​
export default NewNote;

In the code bock above, a form is created and it contains an input field and a textarea field for the note title and note content respectively.

You’ll hook the form up to a function that does the actual addition of note later on.

How to build a React note-taking app with GraphQL

Lastly for the views, let’s add the code for editing an existing view. Open up the EditNote.js file and add the code below to the file.

import React from "react";
const EditNote = () => {
  return (
    <div className="container m-t-20">
      <h1 className="page-title">Edit Note</h1>
​
      <div className="newnote-page m-t-20">
        <form>
          <div className="field">
            <label className="label">Note Title</label>
            <div className="control">
              <input className="input" type="text" placeholder="Note Title" />
            </div>
          </div>
​
          <div class="field">
            <label class="label">Note Content</label>
            <div class="control">
              <textarea
                class="textarea"
                rows="10"
                placeholder="Note Content here..."
              ></textarea>
            </div>
          </div>
​
          <div class="field">
            <div class="control">
              <button class="button is-link">Submit</button>
            </div>
          </div>
        </form>
      </div>
    </div>
  );
}
​
export default EditNote;

In the code bock above, a form is created and it features and input field and a textarea field for the note title and note content respectively.

We’ll hook the form up to a function that does the actual editing of the note data later on.

How to build a React note-taking app with GraphQL

In the step above, the following views were created for the note-taking app:

  • View all existing notes
  • Add a new note
  • Edit an existing note

You can go ahead to start the app in development mode to see the progress made so far. Remember the command yarn start starts the React app in development mode.

In the next step, the functionality required to add, delete and view existing notes will be added to the React app.

Connecting the React App to the GraphQL API

The next step in this tutorial is connecting the React app to the GraphQL API. You’ll be using ApolloClient to interface with the GraphQL API.

ApolloClient is a GraphQL client that help with declarative data fetching from a GraphQL server. It has some built in features that help to implement data caching, pagination, subscriptions e.t.c out of the box.

This helps developers to write less code and with a better structure. One of the best parts about ApolloClient is that it’s adoptable anywhere, in the sense that it can be dropped into any JavaScript app with a GraphQL server and it works.

Let’s get started on connecting the React app to the GraphQL server. The first thing to do is install the various ApolloClient dependencies.

yarn add apollo-boost @apollo/react-hooks graphql graphql-tag apollo-cache-inmemory apollo-link-http
  • apollo-boost: A package containing everything you need to set up ApolloClient.
  • @apollo/react-hooks: React hooks based view layer integration.
  • graphql: Used in parsing your GraphQL queries.
  • graphql-tag: Helpful utilities for parsing GraphQL queries.
  • apollo-cache-inmemory: cache implementation for ApolloClient.
  • apollo-link-http: a standard interface for modifying control flow of GraphQL requests and fetching GraphQL results.

With that done, let’s initiate ApolloClient in our React app. The only thing needed here is the endpoint to our GraphQL server. In our index.js file, let’s import ApolloClient from apollo-boost and add the endpoint for our GraphQL server to the uri property of the client config object.

Edit thesrc/index.js file with the following code.

import React from "react";
import ReactDOM from "react-dom";import { ApolloProvider } from "@apollo/react-hooks";
import { ApolloClient } from "apollo-client";
import { createHttpLink } from "apollo-link-http";
import { ApolloLink } from "apollo-link";
import { InMemoryCache } from "apollo-cache-inmemory";import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";const httpLink = createHttpLink({ uri: "http://localhost:4300/graphql" });const link = ApolloLink.from([httpLink]);const client = new ApolloClient({
  link,
  cache: new InMemoryCache()
});ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById("root")
);// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

In the code block above, the required dependencies are imported from the installed packages. Next, an httpLink constant variable is created and connected to the ApolloClient instance with the GraphQL API. Recall that the GraphQL server is running on http://localhost:4300. ApolloClient is then initialized by passing in the httpLink and a new instance of an InMemoryCache.

Finally, the app is rendered with the root component. App is wrapped with the higher-order component ApolloProvider that gets passed the client as a prop.

Fetching all notes from the GraphQL server

Next thing to do is fetching the all the notes from the GraphQL API and displaying them with the UI already built. To do that, you’ll need to define the query to be sent to GraphQL. Remember while building the GraphQL server we wrote the query to be used in fetching notes on the GraphiQL interface. We’ll do the same here.

Let’s add this query to the AllNotes component. Navigate to the src/AllNotes.js file and let’s start editing.

import React, { Component } from 'react';
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';
import { Link } from 'react-router-dom';const NOTES_QUERY = gql`
{
  allNotes {
    title
    content
    _id
    date
  }
}
`

The query is written here as a JavaScript constant and being parsed with gql. Next, let’s get the display the result from the API and display them with the UI built. In the same AllNotes.js file, replace the existing function with the one below.

const AllNotes = () => {
  const { loading, error, data } = useQuery(NOTES_QUERY);
​
  if (loading) return "Loading...";
  if (error) return `Error! ${error.message}`;
​
  return (
    <div className="container m-t-20">
      <h1 className="page-title">All Notes</h1>
​
      <div className="allnotes-page">
        <div className="columns is-multiline">
          {data.allNotes.map(note => (
            <div className="column is-one-third" key={note._id}>
              <div className="card">
                <header className="card-header">
                  <p className="card-header-title">{note.title}</p>
                </header>
                <div className="card-content">
                  <div className="content">
                    {note.content}
                    <br />
                  </div>
                </div>
                <footer className="card-footer">
                  <Link to={`note/${note._id}`} className="card-footer-item">
                    Edit
                  </Link>
                  <a href="#" className="card-footer-item">
                    Delete
                  </a>
                </footer>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};

Here we’re using the useQuery React Hook to fetch some notes from our GraphQL server and displaying them on the UI. useQuery is the primary API for executing queries in an Apollo application. To run a query within a React component, call useQuery and pass it a GraphQL query string like we did above.

useQuery returns an object from Apollo Client that contains loading, error, and data properties. These props help provide information about the data request to the GraphQL server.

  • loading: Is true as long as the request is still ongoing and the response hasn’t been received.
  • error: In case the request fails, this field will contain information about what exactly went wrong.
  • data: This is the actual data that was received from the server.

Let’s check our progress. You can do a page refresh or start the app if you haven’t with the command yarn start. You should see an error message, specifically, the error message we set above.

How to build a React note-taking app with GraphQL
Upon further inspection which can be done by checking the console of the browser, we can ascertain that it’s a CORS issue.
How to build a React note-taking app with GraphQL

Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a browser to let a web application running at one origin (domain) have permission to access selected resources from a server at a different origin. - MDN

Simply put this means we have to enable our GraphQL server to accept requests from the React app. This can be done by using the cors package which is a node.js package that can be used to enable CORS with various options.

So go back to the notetaking-api project and install the package with the command below.

npm i cors

And proceed to use it in your server by editing the index.js file in the notetaking-api project with the following.

import cors from "cors";
import express from "express";
import graphlHTTP from "express-graphql";
import mongoose from "mongoose";
import schema from "./schema";
​
mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost/notetaking_db", {
  useNewUrlParser: true,
  useUnifiedTopology: true
});
​
const app = express();
const PORT = 4300;
​
app.use(cors());
​
app.get("/", (req, res) => {
  res.json({
    message: "Notetaking API v1"
  });
});
app.use(
  "/graphql",
  graphlHTTP({
    schema: schema,
    graphiql: true
  })
);
app.listen(PORT, () => {
  console.log(`Server is listening on PORT ${PORT}`);
});
​

Now if you refresh the React app, you should get the data from the GraphQL being fetched and displayed.

How to build a React note-taking app with GraphQL

Awesome! You’ve now handled fetching data from the GraphQL server by fetching the list of notes.

Before we go any further, let’s handle errors from the GraphQL server and add a notification system to the React app. To handle errors from the GraphQL server and notifications generally, we’d need to make use of react-notify-toast and apollo-link-error.

react-notify-toast is a React library that help with toast notifications for React apps and apollo-link-error helps to capture GraphQL or network errors. Install both packages with the command below.

yarn add react-notify-toast apollo-link-error

Once installation is done, modify your index.js file to look like the one below.


...
import { onError } from 'apollo-link-error'
import Notifications, {notify} from 'react-notify-toast';
...
​
const errorLink = onError(({ graphQLErrors }) => {
  if (graphQLErrors) graphQLErrors.map(({ message }) => notify.show(message, 'error'))
})
​
const httpLink = createHttpLink({ uri: 'http://localhost:4300/graphql' });
​
const link = ApolloLink.from([
  errorLink,
  httpLink,
]);
​
const client = new ApolloClient({
  link,
  cache: new InMemoryCache()
})
​
ReactDOM.render(
  <ApolloProvider client={client}>
    <Notifications />
    <App />
  </ApolloProvider>,
  document.getElementById('root')
);
registerServiceWorker();

In the code above, the important bit is where the errorLink variable is being created. We are essentially looking out from errors from GraphQL and then displaying them nicely with the notify component.

In the preceding code block, you added the errorLink constant variable which essentially uses the onError function to show a notification whenever there’s an error from the GraphQL server.

Adding notes to GraphQL Server

Let’s see how to add notes to the GraphQL server from the React app. You’ll be editing the NewNote.js file in the src folder.

...
import { useMutation } from "@apollo/react-hooks";
import gql from 'graphql-tag';
​
const NEW_NOTE = gql`
mutation createNote($title: String! $content: String!) {
  createNote( input: {title: $title, content: $content}) {
    _id
    title
    content
    date
  }
}
`
...

In the code block above, we’re utilising the createNote mutation that was defined earlier when we were building out the API.

The useMutation React hook is the primary API for executing mutations in an Apollo application. To run a mutation, you first call useMutation within a React component and pass it a GraphQL string that represents the mutation.

Therefore, we’ll create a GraphQL mutation named NEW_NOTE. The server expects a title and a content to successfully create a new entry, and it returns the id, title, content upon creation.

Next step is to edit the NewNote function so that it utilizes the NEW_NOTE mutation . Edit the file with the code below.

import React, { useState } from "react";
import { withRouter } from "react-router-dom";
import { useMutation } from "@apollo/react-hooks";
import gql from "graphql-tag";const NEW_NOTE = gql`
  mutation createNote($title: String!, $content: String!) {
    createNote(input: { title: $title, content: $content }) {
      _id
      title
      content
      date
    }
  }
`;const NOTES_QUERY = gql`
  {
    allNotes {
      title
      content
      _id
      date
    }
  }
`;const NewNote = () => {
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");const [createNote] = useMutation(NEW_NOTE, {
    update(
      cache,
      {
        data: { createNote }
      }
    ) {
      const { allNotes } = cache.readQuery({ query: NOTES_QUERY });cache.writeQuery({
        query: NOTES_QUERY,
        data: { allNotes: allNotes.concat([createNote]) }
      });
    }
  });return (
    <div className="container m-t-20">
      <h1 className="page-title">New Note</h1><div className="newnote-page m-t-20">
        <form
          onSubmit={e => {
            e.preventDefault();createNote({
              variables: {
                title,
                content,
                date: Date.now()
              }
            });
            history.push("/");
          }}
        >
          <div className="field">
            <label className="label">Note Title</label>
            <div className="control">
              <input
                className="input"
                name="title"
                type="text"
                placeholder="Note Title"
                value={title}
                onChange={e => setTitle(e.target.value)}
              />
            </div>
          </div><div className="field">
            <label className="label">Note Content</label>
            <div className="control">
              <textarea
                className="textarea"
                name="content"
                rows="10"
                placeholder="Note Content here..."
                value={content}
                onChange={e => setContent(e.target.value)}
              ></textarea>
            </div>
          </div><div className="field">
            <div className="control">
              <button className="button is-link">Submit</button>
            </div>
          </div>
        </form>
      </div>
    </div>
  );
};export default NewNote;

When your component renders, useMutation returns a tuple that includes:

  • A mutate function that you can call at any time to execute the mutation
  • An object with fields that represent the current status of the mutation’s execution

The form also has a onSubmit function which allows you to pass title and content as variables props to the GraphQL server.

One other thing we’re doing in the useMutation query is updating the cache otherwise known as interface update. This is essentially ensuring that whatever updates we make to the GraphQL server is also effected on the client in realtime without the need for a page refresh. To do this, the call to useMutation includes an update function. Let’s have a closer look at the update function.

const [createNote] = useMutation(NEW_NOTE, {
    update(cache, { data: { createNote } }) {
      const { allNotes } = cache.readQuery({ query: NOTES_QUERY });cache.writeQuery({
        query: NOTES_QUERY,
        data: { allNotes: allNotes.concat([createNote]) }
      });
    }
  });

The update function is passed a cache object that represents the Apollo Client cache and a data property that contains the result of the mutation. The cache object provides readQuery and writeQuery functions that enable you to execute GraphQL operations on the cache as though you’re interacting with a GraphQL server.

In the code block above, the update function first reads the existing notes from the cache with cache.readQuery. It then adds the newly created note from our mutation to the existing list of notes and writes it back to the cache with cache.writeQuery.

Now, whenever you add a new note, the UI will update to reflect newly cached values.

Next, let’s edit the code so that after a note has been added, the app automatically redirects the notes listing page. To do that, you’d need to import withRouter from react-router-dom in the NewNote.js file. withRouter will be used as a higher order function so that means the NewNote function will be enclosed inside the withRouter function as seen below.

...
import {withRouter} from 'react-router-dom';
...const NewNote = withRouter(({ history }) => {
  ...
});
...

With that done, go ahead to add the line of code below immediately after the createNote function that takes in the variables.

...
createNote({
  variables: {
    title,
    content
  }
});
history.push("/");
...

You’ve now handled the functionality for adding new notes to the GraphQL server. Next, you’ll see how to handle the functionality for editing existing notes.

Editing notes in the GraphQL Server

As seen in the initial React app view, there’s an Edit button that allows you to edit the data in the database. The Edit button is hooked up to the route note/:id where id is the ID of the note we wish to edit. This is done so that we can easily use the ID to find the data in the database and update using Mongoose’s findOneAndUpdate function.

If you check the AllNotes component, you’d see that we’re already passing the ID to the Link component.

<Link to={`note/${note._id}`} className="card-footer-item">Edit</Link>

If you click on the Edit button, it takes you to the Edit Note view but we don’t have the logic to either fetch that particular note’s detail or edit it. Let’s do that now. You start by fetching the note’s details itself.

To fetch the details for a particular note, you’ll first have to write a GraphQL query to fetch the note from the server. In the EditNote.js file, add the code below.

import React, { useState } from "react";
import { useQuery, useMutation } from "@apollo/react-hooks";
import {notify} from 'react-notify-toast';
import gql from 'graphql-tag';const NOTE_QUERY = gql`
query getNote($_id: ID!) {
  getNote (_id: $_id) {
    _id
    title
    content
    date
  }
}
`
...

In the query above, you’re utilising the getNote earlier defined when building the API. The server expects just the _id to successfully fetch the note.

Next, we’ll write the query that will help with updating the notes and since we’ll be sending data, it’s going to be a mutation. Add the block of code below just after the NOTE_QUERY.

...
const UPDATE_NOTE = gql`
  mutation updateNote($_id: ID!, $title: String, $content: String) {
    updateNote(_id: $_id, input: { title: $title, content: $content }) {
      _id
      title
      content
    }
  }
`;
...

In the query above, we’re creating a mutation function that accepts the _id_, title and content as variables. These variables will be sent to the GraphQL server where the appropriate action will be carried out, that is, updating a note.

Next, you’ll define the state using useState that will hold both the title and content of the note we’d like to edit and also implement the Query that will fetch the data from the GraphQL server.

Replace the entire EditNote function with the one below.

const EditNote = ({ match }) => {
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");const { loading, error, data } = useQuery(NOTE_QUERY, {
    variables: {
      _id: match.params.id
    }
  });const [updateNote] = useMutation(UPDATE_NOTE);if (loading) return <div>Fetching note</div>;
  if (error) return <div>Error fetching note</div>;// set the  result gotten from rhe GraphQL server into the note variable.
  const note = data;return (
    <div className="container m-t-20">
      <h1 className="page-title">Edit Note</h1><div className="newnote-page m-t-20">
        <form
          onSubmit={e => {
            // Stop the form from submitting
            e.preventDefault();// set the title of the note to the title in the state, if not's available set to the original title gotten from the GraphQL server
            // set the content of the note to the content in the state, if not's available set to the original content gotten from the GraphQL server
            // pass the id, title and content as variables to the UPDATE_NOTE mutation.
            updateNote({
              variables: {
                _id: note.getNote._id,
                title: title ? title : note.getNote.title,
                content: content ? content : note.getNote.content
              }
            });notify.show("Note was edited successfully", "success");
          }}
        >
          <div className="field">
            <label className="label">Note Title</label>
            <div className="control">
              <input
                className="input"
                type="text"
                name="title"
                placeholder="Note Title"
                defaultValue={note.getNote.title}
                onChange={e => setTitle(e.target.value)}
                required
              />
            </div>
          </div><div className="field">
            <label className="label">Note Content</label>
            <div className="control">
              <textarea
                className="textarea"
                rows="10"
                name="content"
                placeholder="Note Content here..."
                defaultValue={note.getNote.content}
                onChange={e => setContent(e.target.value)}
                required
              ></textarea>
            </div>
          </div><div className="field">
            <div className="control">
              <button className="button is-link">Submit</button>
            </div>
          </div>
        </form>
      </div>
    </div>
  );
};

In the code block above, the useQuery hook contains the NOTE_QUERY query string and an object that contains a variable. In this case the variable is the match.params.id 's value.

useQuery returns an object from Apollo Client that contains loading, error, and data properties. These props help provide information about the data request to the GraphQL server.

The result of the query to the GraphQL server will be stored in the data property which is later set to the const note .

In the form, you’re setting the defaultValue for the input field and textarea to the values gotten from the GraphQL server.

Finally, the form has its own onSubmit function that handles the actual editing of the note. In the onSubmit function, the title and content of the note is sent to the updateNote function which is in turn attached to the useMutation hook.

You’ve now handled the functionality for editing existing notes in the GraphQL server. Next thing to do is to handle deletion of notes from the GraphQL server.

Deleting notes from the GraphQL Server

To delete notes in the database via the React app, you’ll need to make use of the useMutation hook and then use it to send a mutation query (deleteNote) to the GraphQL server.

The first thing we need to do is import the useMutation hook from apollo/react-hooks in the AllNotes.js file and write the query that performs the delete action and that will be sent to the GraphQL server, and then use the useMutation hook to send the query to the server. Edit the AllNotes.js file with the code below.

...
import { useQuery, useMutation } from "@apollo/react-hooks";
import { notify } from "react-notify-toast";...
const DELETE_NOTE_QUERY = gql`
mutation deleteNote($_id: ID!) {
  deleteNote (_id: $_id) {
    title
    content
 _id
  }
}
`const AllNotes = () => {
  const { loading, error, data } = useQuery(NOTES_QUERY);const [deleteNote] = useMutation(DELETE_NOTE_QUERY, {
    update(cache, { data: { deleteNote }}) {
      const { allNotes } = cache.readQuery({ query: NOTES_QUERY });
      const newNotes = allNotes.filter(note => note._id !== deleteNote._id);cache.writeQuery({
        query: NOTES_QUERY,
        data: { allNotes: newNotes }
      });
    }
  });if (loading) return "Loading...";
  if (error) return `Error! ${error.message}`;return (
    <div className="container m-t-20">
      <h1 className="page-title">All Notes</h1><div className="allnotes-page">
        <div className="columns is-multiline">
          {data.allNotes.map(note => (
            <div className="column is-one-third" key={note._id}>
              <div className="card">
                <header className="card-header">
                  <p className="card-header-title">{note.title}</p>
                </header>
                <div className="card-content">
                  <div className="content">
                    {note.content}
                    <br />
                  </div>
                </div>
                <footer className="card-footer">
                  <Link to={`note/${note._id}`} className="card-footer-item">
                    Edit
                  </Link>
                  <button
                    onClick={e => {
                      e.preventDefault();
                      deleteNote({ variables: { _id: note._id } });
                      notify.show("Note was deleted successfully", "success");
                    }}
                    className="card-footer-item"
                  >
                    Delete
                  </button>
                </footer>
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
};
...

In the code block above, we create the deleteNote function and set it to useQuery hook which contains a GraphQL query string. The deleteNote function is later used in the delete’s button onClick handler. It accepts the note’s ID as a variable and then that ID is used to find and delete the entry.

We’re also carrying out interface update here when we delete a note. The useMutation hook also accepts an object which contains an update function in which we’ll be carrying out the interface update.

update(cache, { data: { deleteNote }}) {
  const { allNotes } = cache.readQuery({ query: NOTES_QUERY });
  const newNotes = allNotes.filter(note => note._id !== deleteNote._id);cache.writeQuery({
    query: NOTES_QUERY,
    data: { allNotes: newNotes }
  });
}

In the function above, we first read the available notes using the cache.readQuery method. The readQuery allows us to fetch data without actually making a request to the GraphQL server.

The .filter method is used to check for the particular note that deleted from the page. It works by comparing the _id_ of the deleted note with that of all existing notes and then returns only items that don’t match that of the deleted item. The _id_ of the deleted item is gotten by using payload. payload contains the data that’s being sent to the server. Finally, the cache is updated with the newly filtered data.

That’s it! We have now successfully built a functional web app that has GraphQL as its server and React as its frontend.

How to build a React note-taking app with GraphQL

Conclusion

In this part of the tutorial, you learnt how to build a React app that works with a GraphQL API server. You first started by building a Node.js GraphQL API in the previous part of the tutorial and then you built a frontend app using React.

You also saw how to use Apollo Client to build React apps that interface with a GraphQL server. The React app built in this article allows you to communicate with the GraphQL thanks to Apollo Client.

You can go ahead to extend the application by having some additional features such as pagination, caching, realtime subscriptions e.t.c.

One other thing that was explored was GraphQL’s unique features and some of its advantages over the traditional REST methodology.

If you want to dive deeper and learn more about building web applications with React and GraphQL, you can use any of the resources below:

The code for the GraphQL API can be seen here on GitHub and that of the React app can be seen here.

#reactjs #graphql #web-development #database

What is GEEK

Buddha Community

How to build a React note-taking App with GraphQL
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

Fredy  Larson

Fredy Larson

1595059664

How long does it take to develop/build an app?

With more of us using smartphones, the popularity of mobile applications has exploded. In the digital era, the number of people looking for products and services online is growing rapidly. Smartphone owners look for mobile applications that give them quick access to companies’ products and services. As a result, mobile apps provide customers with a lot of benefits in just one device.

Likewise, companies use mobile apps to increase customer loyalty and improve their services. Mobile Developers are in high demand as companies use apps not only to create brand awareness but also to gather information. For that reason, mobile apps are used as tools to collect valuable data from customers to help companies improve their offer.

There are many types of mobile applications, each with its own advantages. For example, native apps perform better, while web apps don’t need to be customized for the platform or operating system (OS). Likewise, hybrid apps provide users with comfortable user experience. However, you may be wondering how long it takes to develop an app.

To give you an idea of how long the app development process takes, here’s a short guide.

App Idea & Research

app-idea-research

_Average time spent: two to five weeks _

This is the initial stage and a crucial step in setting the project in the right direction. In this stage, you brainstorm ideas and select the best one. Apart from that, you’ll need to do some research to see if your idea is viable. Remember that coming up with an idea is easy; the hard part is to make it a reality.

All your ideas may seem viable, but you still have to run some tests to keep it as real as possible. For that reason, when Web Developers are building a web app, they analyze the available ideas to see which one is the best match for the targeted audience.

Targeting the right audience is crucial when you are developing an app. It saves time when shaping the app in the right direction as you have a clear set of objectives. Likewise, analyzing how the app affects the market is essential. During the research process, App Developers must gather information about potential competitors and threats. This helps the app owners develop strategies to tackle difficulties that come up after the launch.

The research process can take several weeks, but it determines how successful your app can be. For that reason, you must take your time to know all the weaknesses and strengths of the competitors, possible app strategies, and targeted audience.

The outcomes of this stage are app prototypes and the minimum feasible product.

#android app #frontend #ios app #minimum viable product (mvp) #mobile app development #web development #android app development #app development #app development for ios and android #app development process #ios and android app development #ios app development #stages in app development

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

Franz  Becker

Franz Becker

1651604400

React Starter Kit: Build Web Apps with React, Relay and GraphQL.

React Starter Kit — "isomorphic" web app boilerplate   

React Starter Kit is an opinionated boilerplate for web development built on top of Node.js, Express, GraphQL and React, containing modern web development tools such as Webpack, Babel and Browsersync. Helping you to stay productive following the best practices. A solid starting point for both professionals and newcomers to the industry.

See getting started guide, demo, docs, roadmap  |  Join #react-starter-kit chat room on Gitter  |  Visit our sponsors:

 

Hiring

Getting Started

Customization

The master branch of React Starter Kit doesn't include a Flux implementation or any other advanced integrations. Nevertheless, we have some integrations available to you in feature branches that you can use either as a reference or merge into your project:

You can see status of most reasonable merge combination as PRs labeled as TRACKING

If you think that any of these features should be on master, or vice versa, some features should removed from the master branch, please let us know. We love your feedback!

Comparison

 

React Starter Kit

React Static Boilerplate

ASP.NET Core Starter Kit

App typeIsomorphic (universal)Single-page applicationSingle-page application
Frontend
LanguageJavaScript (ES2015+, JSX)JavaScript (ES2015+, JSX)JavaScript (ES2015+, JSX)
LibrariesReact, History, Universal RouterReact, History, ReduxReact, History, Redux
RoutesImperative (functional)DeclarativeDeclarative, cross-stack
Backend
LanguageJavaScript (ES2015+, JSX)n/aC#, F#
LibrariesNode.js, Express, Sequelize,
GraphQL
n/aASP.NET Core, EF Core,
ASP.NET Identity
SSRYesn/an/a
Data APIGraphQLn/aWeb API

Backers

♥ React Starter Kit? Help us keep it alive by donating funds to cover project expenses via OpenCollective or Bountysource!

lehneres Tarkan Anlar Morten Olsen Adam David Ernst Zane Hitchcox  

How to Contribute

Anyone and everyone is welcome to contribute to this project. The best way to start is by checking our open issues, submit a new issue or feature request, participate in discussions, upvote or downvote the issues you like or dislike, send pull requests.

Learn More

Related Projects

  • GraphQL Starter Kit — Boilerplate for building data APIs with Node.js, JavaScript (via Babel) and GraphQL
  • Membership Database — SQL schema boilerplate for user accounts, profiles, roles, and auth claims
  • Babel Starter Kit — Boilerplate for authoring JavaScript/React.js libraries

Support

License

Copyright © 2014-present Kriasoft, LLC. This source code is licensed under the MIT license found in the LICENSE.txt file. The documentation to the project is licensed under the CC BY-SA 4.0 license.


Author: kriasoft
Source Code: https://github.com/kriasoft/react-starter-kit
License: MIT License

#graphql #react 

Carmen  Grimes

Carmen Grimes

1595491178

Best Electric Bikes and Scooters for Rental Business or Campus Facility

The electric scooter revolution has caught on super-fast taking many cities across the globe by storm. eScooters, a renovated version of old-school scooters now turned into electric vehicles are an environmentally friendly solution to current on-demand commute problems. They work on engines, like cars, enabling short traveling distances without hassle. The result is that these groundbreaking electric machines can now provide faster transport for less — cheaper than Uber and faster than Metro.

Since they are durable, fast, easy to operate and maintain, and are more convenient to park compared to four-wheelers, the eScooters trend has and continues to spike interest as a promising growth area. Several companies and universities are increasingly setting up shop to provide eScooter services realizing a would-be profitable business model and a ready customer base that is university students or residents in need of faster and cheap travel going about their business in school, town, and other surrounding areas.

Electric Scooters Trends and Statistics

In many countries including the U.S., Canada, Mexico, U.K., Germany, France, China, Japan, India, Brazil and Mexico and more, a growing number of eScooter users both locals and tourists can now be seen effortlessly passing lines of drivers stuck in the endless and unmoving traffic.

A recent report by McKinsey revealed that the E-Scooter industry will be worth― $200 billion to $300 billion in the United States, $100 billion to $150 billion in Europe, and $30 billion to $50 billion in China in 2030. The e-Scooter revenue model will also spike and is projected to rise by more than 20% amounting to approximately $5 billion.

And, with a necessity to move people away from high carbon prints, traffic and congestion issues brought about by car-centric transport systems in cities, more and more city planners are developing more bike/scooter lanes and adopting zero-emission plans. This is the force behind the booming electric scooter market and the numbers will only go higher and higher.

Companies that have taken advantage of the growing eScooter trend develop an appthat allows them to provide efficient eScooter services. Such an app enables them to be able to locate bike pick-up and drop points through fully integrated google maps.

List of Best Electric Bikes for Rental Business or Campus Facility 2020:

It’s clear that e scooters will increasingly become more common and the e-scooter business model will continue to grab the attention of manufacturers, investors, entrepreneurs. All this should go ahead with a quest to know what are some of the best electric bikes in the market especially for anyone who would want to get started in the electric bikes/scooters rental business.

We have done a comprehensive list of the best electric bikes! Each bike has been reviewed in depth and includes a full list of specs and a photo.

Billy eBike

mobile-best-electric-bikes-scooters https://www.kickstarter.com/projects/enkicycles/billy-were-redefining-joyrides

To start us off is the Billy eBike, a powerful go-anywhere urban electric bike that’s specially designed to offer an exciting ride like no other whether you want to ride to the grocery store, cafe, work or school. The Billy eBike comes in 4 color options – Billy Blue, Polished aluminium, Artic white, and Stealth black.

Price: $2490

Available countries

Available in the USA, Europe, Asia, South Africa and Australia.This item ships from the USA. Buyers are therefore responsible for any taxes and/or customs duties incurred once it arrives in your country.

Features

  • Control – Ride with confidence with our ultra-wide BMX bars and a hyper-responsive twist throttle.
  • Stealth- Ride like a ninja with our Gates carbon drive that’s as smooth as butter and maintenance-free.
  • Drive – Ride further with our high torque fat bike motor, giving a better climbing performance.
  • Accelerate – Ride quicker with our 20-inch lightweight cutout rims for improved acceleration.
  • Customize – Ride your own way with 5 levels of power control. Each level determines power and speed.
  • Flickable – Ride harder with our BMX /MotoX inspired geometry and lightweight aluminum package

Specifications

  • Maximum speed: 20 mph (32 km/h)
  • Range per charge: 41 miles (66 km)
  • Maximum Power: 500W
  • Motor type: Fat Bike Motor: Bafang RM G060.500.DC
  • Load capacity: 300lbs (136kg)
  • Battery type: 13.6Ah Samsung lithium-ion,
  • Battery capacity: On/off-bike charging available
  • Weight: w/o batt. 48.5lbs (22kg), w/ batt. 54lbs (24.5kg)
  • Front Suspension: Fully adjustable air shock, preload/compression damping /lockout
  • Rear Suspension: spring, preload adjustment
  • Built-in GPS

Why Should You Buy This?

  • Riding fun and excitement
  • Better climbing ability and faster acceleration.
  • Ride with confidence
  • Billy folds for convenient storage and transportation.
  • Shorty levers connect to disc brakes ensuring you stop on a dime
  • belt drives are maintenance-free and clean (no oil or lubrication needed)

**Who Should Ride Billy? **

Both new and experienced riders

**Where to Buy? **Local distributors or ships from the USA.

Genze 200 series e-Bike

genze-best-electric-bikes-scooters https://www.genze.com/fleet/

Featuring a sleek and lightweight aluminum frame design, the 200-Series ebike takes your riding experience to greater heights. Available in both black and white this ebike comes with a connected app, which allows you to plan activities, map distances and routes while also allowing connections with fellow riders.

Price: $2099.00

Available countries

The Genze 200 series e-Bike is available at GenZe retail locations across the U.S or online via GenZe.com website. Customers from outside the US can ship the product while incurring the relevant charges.

Features

  • 2 Frame Options
  • 2 Sizes
  • Integrated/Removable Battery
  • Throttle and Pedal Assist Ride Modes
  • Integrated LCD Display
  • Connected App
  • 24 month warranty
  • GPS navigation
  • Bluetooth connectivity

Specifications

  • Maximum speed: 20 mph with throttle
  • Range per charge: 15-18 miles w/ throttle and 30-50 miles w/ pedal assist
  • Charging time: 3.5 hours
  • Motor type: Brushless Rear Hub Motor
  • Gears: Microshift Thumb Shifter
  • Battery type: Removable Samsung 36V, 9.6AH Li-Ion battery pack
  • Battery capacity: 36V and 350 Wh
  • Weight: 46 pounds
  • Derailleur: 8-speed Shimano
  • Brakes: Dual classic
  • Wheels: 26 x 20 inches
  • Frame: 16, and 18 inches
  • Operating Mode: Analog mode 5 levels of Pedal Assist Thrott­le Mode

Norco from eBikestore

norco-best-electric-bikes-scooters https://ebikestore.com/shop/norco-vlt-s2/

The Norco VLT S2 is a front suspension e-Bike with solid components alongside the reliable Bosch Performance Line Power systems that offer precise pedal assistance during any riding situation.

Price: $2,699.00

Available countries

This item is available via the various Norco bikes international distributors.

Features

  • VLT aluminum frame- for stiffness and wheel security.
  • Bosch e-bike system – for their reliability and performance.
  • E-bike components – for added durability.
  • Hydraulic disc brakes – offer riders more stopping power for safety and control at higher speeds.
  • Practical design features – to add convenience and versatility.

Specifications

  • Maximum speed: KMC X9 9spd
  • Motor type: Bosch Active Line
  • Gears: Shimano Altus RD-M2000, SGS, 9 Speed
  • Battery type: Power Pack 400
  • Battery capacity: 396Wh
  • Suspension: SR Suntour suspension fork
  • Frame: Norco VLT, Aluminum, 12x142mm TA Dropouts

Bodo EV

bodo-best-electric-bikes-scootershttp://www.bodoevs.com/bodoev/products_show.asp?product_id=13

Manufactured by Bodo Vehicle Group Limited, the Bodo EV is specially designed for strong power and extraordinary long service to facilitate super amazing rides. The Bodo Vehicle Company is a striking top in electric vehicles brand field in China and across the globe. Their Bodo EV will no doubt provide your riders with high-level riding satisfaction owing to its high-quality design, strength, breaking stability and speed.

Price: $799

Available countries

This item ships from China with buyers bearing the shipping costs and other variables prior to delivery.

Features

  • Reliable
  • Environment friendly
  • Comfortable riding
  • Fashionable
  • Economical
  • Durable – long service life
  • Braking stability
  • LED lighting technology

Specifications

  • Maximum speed: 45km/h
  • Range per charge: 50km per person
  • Charging time: 8 hours
  • Maximum Power: 3000W
  • Motor type: Brushless DC Motor
  • Load capacity: 100kg
  • Battery type: Lead-acid battery
  • Battery capacity: 60V 20AH
  • Weight: w/o battery 47kg

#android app #autorent #entrepreneurship #ios app #minimum viable product (mvp) #mobile app development #news #app like bird #app like bounce #app like lime #autorent #best electric bikes 2020 #best electric bikes for rental business #best electric kick scooters 2020 #best electric kickscooters for rental business #best electric scooters 2020 #best electric scooters for rental business #bird scooter business model #bird scooter rental #bird scooter rental cost #bird scooter rental price #clone app like bird #clone app like bounce #clone app like lime #electric rental scooters #electric scooter company #electric scooter rental business #how do you start a moped #how to start a moped #how to start a scooter rental business #how to start an electric company #how to start electric scooterrental business #lime scooter business model #scooter franchise #scooter rental business #scooter rental business for sale #scooter rental business insurance #scooters franchise cost #white label app like bird #white label app like bounce #white label app like lime