In today’s web development ecosystem, creating efficient and scalable applications often involves combining powerful technologies. This blog will guide you through building a basic CRUD (Create, Read, Update, Delete) application using GraphQL, React, Node.js, and MongoDB. By the end, you’ll have a clear understanding of how these technologies work together and how to set up your project from scratch.
Why This Tech Stack?
- GraphQL: A modern API query language that allows clients to request exactly what they need, improving performance and flexibility.
- Node.js: A JavaScript runtime for building fast, scalable backend applications.
- MongoDB: A NoSQL database designed for high availability, scalability, and flexibility.
- React: A powerful JavaScript library for building dynamic user interfaces. This combination ensures you’re using state-of-the-art tools for building a modern web application.
Project Overview
In this project, we’ll create a simple application where users can:
- Add new items to a database (Create).
- View all items (Read).
- Update existing items (Update).
- Delete items from the database (Delete).
Project Structure
Here is the structure of the project:
├── backend
│ ├── index.js # Main server file
│ ├── schema.js # GraphQL schema and resolvers
│ └── models
│ └── Item.js # MongoDB model
├── frontend
│ ├── src
│ │ ├── App.js # Main React component
│ │ ├── components
│ │ │ └── ItemList.js # Display list of items
│ │ └── graphql
│ │ ├── queries.js # GraphQL queries
│ │ └── mutations.js # GraphQL mutations
Prerequisites
Make sure you have the following installed:
- Node.js (v14 or later)
- MongoDB
Step 1: Initialize the Backend
Navigate to your desired directory and create a backend folder:
mkdir backend && cd backend
Initialize a Node.js project:
npm init -y
Install the necessary dependencies:
npm install express graphql express-graphql mongoose
Step 2: Create the MongoDB Model
Inside the backend directory, create a folder named models and add a file called Item.js:
const mongoose = require('mongoose');
const ItemSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String, required: true },
});
module.exports = mongoose.model('Item', ItemSchema);
Step 3: Define the GraphQL Schema
Create a file named schema.js in the backend directory:
const { GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLID, GraphQLList } = require('graphql');
const Item = require('./models/Item');
const ItemType = new GraphQLObjectType({
name: 'Item',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
description: { type: GraphQLString },
}),
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
items: {
type: new GraphQLList(ItemType),
resolve() {
return Item.find();
},
},
},
});
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addItem: {
type: ItemType,
args: {
name: { type: GraphQLString },
description: { type: GraphQLString },
},
resolve(_, args) {
const item = new Item({
name: args.name,
description: args.description,
});
return item.save();
},
},
deleteItem: {
type: ItemType,
args: { id: { type: GraphQLID } },
resolve(_, args) {
return Item.findByIdAndDelete(args.id);
},
},
updateItem: {
type: ItemType,
args: {
id: { type: GraphQLID },
name: { type: GraphQLString },
description: { type: GraphQLString },
},
resolve(_, args) {
return Item.findByIdAndUpdate(
args.id,
{ name: args.name, description: args.description },
{ new: true }
);
},
},
},
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation,
});
Step 4: Create the Server
Create an index.js file in the backend directory:
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const mongoose = require('mongoose');
const schema = require('./schema');
const app = express();
mongoose
.connect('mongodb://localhost:27017/crud-app', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error(err));
app.use('/graphql', graphqlHTTP({
schema,
graphiql: true,
}));
app.listen(4000, () => console.log('Server running on http://localhost:4000/graphql'));
Run the server:
node index.js
Setting Up the Frontend
Step 1: Initialize the React App
Navigate to the main directory and create a frontend folder:
npx create-react-app frontend
cd frontend
Install Apollo Client:
npm install @apollo/client graphql
Step 2: Create GraphQL Queries and Mutations
In the src folder, create a graphql folder with two files: queries.js and mutations.js.
queries.js
import { gql } from '@apollo/client';
export const GET_ITEMS = gql`
query GetItems {
items {
id
name
description
}
}
`;
mutations.js
import { gql } from '@apollo/client';
export const ADD_ITEM = gql`
mutation AddItem($name: String!, $description: String!) {
addItem(name: $name, description: $description) {
id
name
description
}
}
`;
Step 3: Build the Frontend UI
Edit the App.js file to include ApolloProvider and display items:
import React from 'react';
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
import ItemList from './components/ItemList';
consi client = new ApolloClient({
uri: 'http://localhost:4000/graphql',
cache: new InMemoryCache(),
});
function App() {
return (
<ApolloProvider client={client}>
<div className="App">
<h1>CRUD Application</h1>
<ItemList />
</div>
</ApolloProvider>
);
}
export default App;
Create the ItemList.js component:
import React from 'react';
import { useQuery } from '@apollo/client';
import { GET_ITEMS } from '../graphql/queries';
function ItemList() {
const { loading, error, data } = useQuery(GET_ITEMS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<ul>
{data.items.map(item => (
<li key={item.id}>{item.name}: {item.description}</li>
))}
</ul>
);
}
export default ItemList;
Run the frontend:
npm start
Conclusion
Congratulations! You’ve built a basic CRUD application with GraphQL, React, Node.js, and MongoDB. This project lays the foundation for more advanced features, such as authentication, pagination, and complex relationships. Keep experimenting and enhancing your application to master this tech stack!
Top comments (0)