project-manage-app.mp4
- Project Management App
- Initialize application
- GraphiQL
- Initiate Mongodb - Mongodb atlas, Mongodb compass
- Build client side with React framework.
- Deploy with heroku
- References
A MERN stack application to manage clients and project data that can make CRUD functionality with simple web page.
- Built backend with expressjs and handled by using graphQL mutation.
- Used graphiql for checking graphql schema on the browser.
- Made cloud-based database by using mongodb atlas and controled with mongodb compass.
- Build client side with React and apollo, graphql, react-router-dom, react-icons packages.
- Deploy with PaaS service heroku application.
- Resource: Git repo | Demo
- initialize project:
npm init -y
->package.json
created - install dependencies:
npm i express express-graphql graphql mongoose cors colors
->node_modules
folder andpackage-lock.json
file created. - install dev mode dependencires:
npm i -D nodemon dotenv
- change
package.json
scripts setting.
"scripts": {
"start": "node server/index.js",
"dev": "nodemon server/index.js"
}
Now you can start server by using npm run dev
command inside of working directory.
GraphiQL is the GraphQL integrated development environment (IDE). We can make query and check data with GraphiQL on the localhost:5000/graphql
.
Mongodb atlas is a cloud-based Mongodb service that don't need to install any program on the local machine.
Sign up with google acount and build a database.
Select share version and create cluster.
Add my local ip address and finish
Create database with own name mgmt_db
and clients
.
Download and install Mongodb compass.
On the mongodb atlas, choose overview menu and click connect
.
Select connect to the compass and copy the connection string. And change <username>
and <password>
. After that, you can see database connected with atlas on the compass.
To connect with application, select go back
and make a choice connect your application
. Copy connection string inside of .env
file as a MONGO_URI
variable. (Change , and add mgmt_db
after mongodb.net/
)
By using mongoose
module, you can connect MongoDB with application. Inside of config
folder, db.js
have a connectDB
as a module.
const mongoose = require('mongoose');
const connectDB = async () => {
const conn = await mongoose.connect(process.env.MONGO_URI);
console.log(`MongoDB Connected: ${conn.connection.host}`.cyan.underline.bold);
};
module.exports = connectDB;
If you want to anticipate message as specific color and underline, we can use colors
module.
In order to fetch data from MongoDB after connected with, we need to make new schema for MongoDB again not for GraphQL. In this project, Client.js
and Project.js
file was made inside of models
folder. And changed schema.js
return values of each client and project.
For handling MongoDB database with GraphQL, mutation
object type can be added inside of schema.js
. Name of object is Mutation
and you can add client data by using GraphiQL like below.
And you can find new client data was added successfully on the MongoDB client database with MongoDB compass. Object ID is automatically created by MongoDB.
In the same way, we can add deleteClient
field to delete a client data with GraphiQL on the browser.
project
database also can be added, deleted and updated by ustin mutation
object type. This code is added into schema.js
.
We can initialize react app in the client
folder with npx create-react-app client
command. After that, some packages should be installed by npm i @apollo/client graphql react-router-dom react-icons
command.
Apollo Client is a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. Use it to fetch, cache, and modify application data, all while automatically updating your UI. Apollo Client helps you structure code in an economical, predictable, and declarative way that's consistent with modern development practices. The core @apollo/client library provides built-in integration with React, and the larger Apollo community maintains integrations for other popular view layers.
- Whenever Apollo Client fetches query results from your server, it automatically caches those results locally. This makes later executions of that same query extremely fast.
- Apollo Client stores the results of your GraphQL queries in a local, normalized, in-memory cache. This enables Apollo Client to respond almost immediately to queries for already-cached data, without even sending a network request.
The react-router-dom package contains bindings for using React Router
in web applications.
React Router includes three main packages:
react-router
, the core package for the routerreact-router-dom
, which contains the DOM bindings for React Router. In other words, the router components for websitesreact-router-native
, which contains the React Native bindings for React Router. In other words, the router components for an app development environment using React Native
React Router DOM enables you to implement dynamic routing in a web app. Unlike the traditional routing architecture in which the routing is handled in a configuration outside of a running app, React Router DOM facilitates component-based routing according to the needs of the app and platform.
Include popular icons in your React projects easily with react-icons, which utilizes ES6 imports that allows you to include only the icons that your project is using.
In order to use state management library Apollo Client, we need to import ApolloProvider
,ApolloClient
,InMemoryCache
from @apollo/client
. And make new ApolloClient class with client
variable.
- App.js
import Header from './components/Header';
import { ApolloProvider, ApolloClient, InMemoryCache } from '@apollo/client';
const client = new ApolloClient({
uri: 'http://localhost:5000/graphql', //backend graphql url
cache: new InMemoryCache(),
});
function App() {
return (
<>
<ApolloProvider client={client}>
<Header />
<div className="container">
<h1>Hello World</h1>
</div>
</ApolloProvider>
</>
);
}
export default App;
src/components/Clients.jsx
has a role to fetch and display clients data. For doing this, we need to import gql
from @apollo/clients
. The query we want to execute by wrapping it in the gql template literal defined like below.
const GET_CLIENTS = gql`
query getClinets {
clients {
id
name
email
phone
}
}
`
Whenever this component renders, the useQuery hook automatically executes our query and returns a result object containing loading, error, and data properties:
- Apollo Client tracks a query's error and loading state for you, which are reflected in the loading and error properties.
- When the result of your query comes back, it's attached to the data property.
At this project, we should show up client data like this.
export default function Clients() {
const { loading, error, data } = useQuery(GET_CLIENTS);
if (loading) return <p>loading...</p>;
if (error) return <p>Something Went Wrong</p>;
return (
<>
{!loading && !error && (
<table className="table table-hover mt-3">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th></th>
</tr>
</thead>
<tbody>
{data.clients.map((client) => (
<ClientRow key={client.id} client={client} />
))}
</tbody>
</table>
)}
</>
);
}
Then we can see the Project Management App like below.
In order to show up the project view page, we need to use react-router-dom
on the App.js
.
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'
After that, you can add Router
setting like below. Inside of <Router>
, we can make several <Route>
another inside of <Routes>
. Each of route has their own path address and component directed to link. (<Home />
,<Project />
,<NotFound />
).
<>
<ApolloProvider client={client}>
<Router>
<Header />
<div className="container">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/projects/:id" element={<Project />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</Router>
</ApolloProvider>
</>
-
useParams
: The useParams hook returns an object of key/value pairs of the dynamic params from the current URL that were matched by the . Child routes inherit all params from their parent routes. In this project,Project.jsx
usesuseParams
for parsingid
data from which isProjectCard.jsx
indicated. -
useNavigate
: The useNavigate hook returns a function that lets you navigate programmatically, for example after a form is submitted. If using replace: true, the navigation will replace the current entry in the history stack instead of adding a new one. In order to move home page after delete project byonClick
, we can takeuseNavigate()
withonCompleted
key value.
DeleteProjectButton.jsx
export default function DeleteProjectButton({ projectId }) {
const navigate = useNavigate();
const [deleteProject] = useMutation(DELETE_PROJECT, {
variables: { id: projectId },
onCompleted: () => navigate('/'),
refetchQueries: [{ query: GET_PROJECTS }],
});
return (
<div className="d-flex mt-5 ms-auto">
<button className="btn btn-danger m-2" onClick={deleteProject}>
<FaTrash className="icon" /> Delete Project
</button>
</div>
);
}
Before start heroku deploy process, we need to add some codes on server/index.js
for production environment.
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../client/build')));
app.get('*', (req, res) =>
res.sendFile(
path.resolve(__dirname, '../', 'client', 'build', 'index.html')
)
);
} else {
app.get('/', (req, res) => res.send('Please set to production'));
}
Enter npm run build
command inside of client
folder. Then project will be built and build
folder is ready to be deployed.
After sign in heroku website, heroku login
on the project folder root location. And create new app by using heroku create mernappsh
. (mernappsh is a name of heroku application).
You can check heroku app with https://mernappsh.herokuapp.com/
.
Go to the heroku dashboard, select mernappsh
app and select Settings
. Add Config Vars like below.
Then we can start git push process.
git add .
git commit -m 'Prepare Deploy'
git push heroku master
If there is H10 error, this video clip would be helpful. In order to use graphql in heroku, uri http://localhost:5000
should be deleted related with ApolloClient. You can check this video clip.