Open In App

Task Manager App using Express, React and GraphQL.

Last Updated : 30 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

The Task Manager app tool is designed to simplify task management with CRUD operation: creation, deletion, and modification of tasks. Users can easily generate new tasks, remove completed ones, and update task details. In this step-by-step tutorial, you will learn the process of building a Basic Task Manager App with Express, React and GraphQL.

Preview of final output: Let us have a look at how the final application will look like.

sdfsghj

Project Preview

Prerequisites

Approach to create Task Manager App:

  • Creating a Task Manager application involves using React for the front end and Express with GraphQL for the back end.
  • The front end is built with React, a JavaScript library for building user interfaces, and utilizes Apollo Client for state management.
  • Apollo Client is employed for handling data fetching and mutations through GraphQL queries in the front end.
  • Communication between the front end and back end occurs via Express, a Node.js framework, with express-graphql middleware managing GraphQL queries.
  • The backend defines a GraphQL schema with queries and mutations specifically designed for tasks.
  • Task management is handled in memory on the server side, utilizing GraphQL’s capabilities for querying, creating, updating, and deleting tasks.
  • Apollo Client’s useQuery and useMutation hooks facilitate interaction between the frontend and backend, fetching tasks and updating the UI dynamically.
  • The application follows a client-server architecture, where React interacts with Express through GraphQL for CRUD operations on tasks.

Steps to create Application and install dependencies

Step 1: Create a new directory for your project and navigate it to the terminal using the following commands

mkdir task-manager-app
cd task-manager-app

Step 2: Create a new React app using Create React App.

npx create-react-app client
cd client

Step 3: Install the required dependencies.

npm install @apollo/client graphql

Project Structure:

directorystructure

Final Directoruy structure

The updated dependencies in package.json file will look like :

Frontend Dependencies:

"dependencies":{    
"react":"18.2.0",
"@apollo/client": "3.8.8",
"@apollo/react-hooks": "4.0.0",
"react-dom": "18.2.0",
"graphql": "16.8.11"
}

Backend Dependencies

"dependencies": {    
"express": "4.18.2",
"express-graphql": "0.12.0",
"graphql": "15.8.0",
"cors": "2.8.5",
"apollo-server-express": "3.13.0"
}

Example: Add the following code in client/src/App.js

Javascript




//App.js
 
import React, { useState } from "react";
import {
    useQuery,
    useMutation,
    gql,
    ApolloProvider,
    ApolloClient,
    InMemoryCache,
} from "@apollo/client";
import "./App.css";
 
const GET_TASKS = gql`
    query {
        tasks {
            id
            title
            description
        }
    }
`;
 
const CREATE_TASK = gql`
    mutation CreateTask($title: String!, $description: String!) {
        createTask(title: $title, description: $description) {
            id
            title
            description
        }
    }
`;
 
const DELETE_TASK = gql`
    mutation DeleteTask($id: ID!) {
        deleteTask(id: $id)
    }
`;
 
const UPDATE_TASK = gql`
    mutation UpdateTask($id: ID!, $title: String, $description: String) {
        updateTask(id: $id, title: $title, description: $description) {
            id
            title
            description
        }
    }
`;
 
function App() {
    const { loading, error, data } = useQuery(GET_TASKS);
    const [createTask] = useMutation(CREATE_TASK);
    const [deleteTask] = useMutation(DELETE_TASK);
    const [updateTask] = useMutation(UPDATE_TASK);
 
    const [newTask, setNewTask] = useState({ title: "", description: "" });
 
    if (loading) return <p>Loading...</p>;
    if (error) return <p>Error: {error.message}</p>;
 
    const handleCreateTask = () => {
        createTask({
            variables: newTask,
            refetchQueries: [{ query: GET_TASKS }],
        });
        setNewTask({ title: "", description: "" });
    };
 
    const handleDeleteTask = (id) => {
        deleteTask({
            variables: { id },
            refetchQueries: [{ query: GET_TASKS }],
        });
    };
 
    const handleUpdateTask = (id, title, description) => {
        updateTask({
            variables: { id, title, description },
            refetchQueries: [{ query: GET_TASKS }],
        });
    };
 
    return (
        <div>
            <h1>GeeksforGeeks</h1>
            <h3>Task Manager</h3>
            <div>
                <h2>Create Task</h2>
                <input
                    type="text"
                    placeholder="Title"
                    value={newTask.title}
                    onChange={(e) =>
                        setNewTask({ ...newTask, title: e.target.value })
                    }
                />
                <input
                    type="text"
                    placeholder="Description"
                    value={newTask.description}
                    onChange={(e) =>
                        setNewTask({ ...newTask, description: e.target.value })
                    }
                />
                <button onClick={handleCreateTask}>Create</button>
            </div>
            <div>
                <h2>Tasks</h2>
                <ul>
                    {data.tasks.map((task) => (
                        <li key={task.id}>
                            {task.title} - {task.description}
                            <button onClick={() => handleDeleteTask(task.id)}>
                                Delete
                            </button>
                            <button
                                onClick={() => {
                                    const updatedTitle = prompt(
                                        "Enter new title:",
                                        task.title
                                    );
                                    const updatedDescription = prompt(
                                        "Enter new description:",
                                        task.description
                                    );
                                    handleUpdateTask(
                                        task.id,
                                        updatedTitle,
                                        updatedDescription
                                    );
                                }}
                            >
                                Update
                            </button>
                        </li>
                    ))}
                </ul>
            </div>
        </div>
    );
}
 
const client = new ApolloClient({
    cache: new InMemoryCache(),
});
 
function ApolloApp() {
    return (
        <ApolloProvider client={client}>
            <App />
        </ApolloProvider>
    );
}
export default ApolloApp;


CSS




/*App.css*/
 
body {
  font-family: "Roboto", sans-serif;
  margin: 0;
  padding: 0;
  background-color: #f4f4f4;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}
 
.container {
  width: 80%;
  padding: 20px;
  background-color: #fff;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  border-radius: 8px;
}
 
h1 {
  font-family: "Open Sans", sans-serif;
  color: #037f07;
  margin-bottom: 10px;
  text-align: center;
}
 
h3 {
  font-family: "Arial", sans-serif;
  color: #333;
  margin-bottom: 20px;
  text-align: center;
  font-size: 20px;
}
 
form {
  margin-bottom: 20px;
}
 
input {
  padding: 10px;
  margin-right: 10px;
  width: 200px;
}
 
button {
  padding: 10px 16px;
  background-color: #4caf50;
  color: white;
  border: none;
  cursor: pointer;
}
 
ul {
  list-style-type: none;
  padding: 0;
}
 
li {
  margin-bottom: 20px;
  padding: 20px;
  border: 1px solid #ddd;
  background-color: #f9f9f9;
  border-radius: 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
 
button.delete {
  background-color: #e74c3c;
}
 
button.update {
  background-color: #3498db;
  margin-right: 5px;
}


Now the Frontend of the app is ready and we are moving forward to the backand of the app.

Step 4: In the main project directory, create a new file named server.js for the Express server.

npm init -y
touch server.js


Step 5: Install the required dependencies for Express and GraphQL using below command :

npm install express express-graphql graphql cors


Example: Now, copy and paste the following code into server.js:

Javascript




//server.js
 
const express = require("express");
const { graphqlHTTP } = require("express-graphql");
const { buildSchema } = require("graphql");
const cors = require("cors");
 
let tasks = [];
 
const schema = buildSchema(`
  type Task {
    id: ID!
    title: String!
    description: String!
  }
 
  type Query {
    tasks: [Task]
  }
 
  type Mutation {
    createTask(title: String!, description: String!): Task
    deleteTask(id: ID!): Boolean
    updateTask(id: ID!, title: String, description: String): Task
  }
`);
 
const root = {
    tasks: () => tasks,
    createTask: ({ title, description }) => {
        const newTask = { id: tasks.length + 1, title, description };
        tasks.push(newTask);
        return newTask;
    },
    deleteTask: ({ id }) => {
        tasks = tasks.filter((task) => task.id !== parseInt(id));
        return true;
    },
    updateTask: ({ id, title, description }) => {
        const taskIndex = tasks.findIndex((task) => task.id === parseInt(id));
        if (taskIndex !== -1) {
            tasks[taskIndex] = { ...tasks[taskIndex], title, description };
            return tasks[taskIndex];
        }
        return null;
    },
};
 
const app = express();
app.use(cors());
 
app.use("/graphql", graphqlHTTP({ schema, rootValue: root, graphiql: true }));
 
const port = 3001;
app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}/graphql`);
});


Step 6: Run and Test the App

Backend:

node server.js 

Frontend:

cd client 
npm start

Output :

ezgifcom-video-to-gif-converter

Task Manager App using Express, React and GraphQL



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads