Hello and welcome to the 3rd part of Let's Build a MySQL Node.js CRUD App series! In the previous article, we have implemented all our GET, POST, PUT and DELETE routes in our server.
If you haven't read the previous article, please find it here.
In this part, we will be working on our front-end with React to complete our MySQL CRUD app!
Step 1: Install npm packages
Install axios and cors to allow our app to make requests to the server. Install react-hook-form for easy form handling in React.
npm install axios cors react-hook-form
Step 2: Import cors
In server.js
, include the import statement at the top to use cors.
const cors = require("cors");
Then, to use it, add this line below the const app
line.
app.use(cors());
This will allow our client-side at localhost:3001
to be able to make requests to the server at port 3000
. To understand more about CORS, feel free to read this article on Introduction to Cross-Origin Resource Sharing.
Step 3: Read Reviews
In App.js
, we want to get and display the reviews from MySQL for users to read. To do so, we first import the following:
import { useState, useEffect } from "react";
import axios from "axios";
Next, our code will proceed as:
- Initialize an array called
reviews
, which contains all review data - Create function to GET all the reviews from server store to
reviews
array. - Create a
useEffect
hook to updatereviews
// 1.
const [reviews, setReviews] = useState([]);
// 2.
const getReviews = () => {
axios.get("http://localhost:3000/reviews").then((res) => {
setReviews(res.data);
});
};
// 3.
useEffect(() => {
getReviews();
}, [reviews]);
Lastly, to display the data in reviews
, we use map()
in the return function and envelop it with a <div className="reviews">
as shown:
<div className="reviews">
{reviews.map((item) => {
return (
<div className="review">
<h3>Title: {item.book_title}</h3>
<h3>Review: {item.book_review}</h3>
<h3>Rating: {item.book_rating}</h3>
</div>
);
})}
</div>
Then run the server with nodemon server.js
and start the React app with npm start
.
Our app should display data from our database immediately after launching.
Step 3: Create Reviews
Now let's create the components for our React app to perform the Create operation to our database.
Create a file called Add.js
, which will be the component that allows the user to create and add a new book review into the database by submitting a form using react-hook-form
and axios
.
In this file, add the following import statements at the top.
import { useForm } from "react-hook-form";
import axios from "axios";
Then, we will code the following:
- Initialize form using
useForm
- Create an onSubmit handler function that will insert the submitted form data into the database.
- Update the reviews array in App.js
export default function Add(props) {
// 1.
const { register, handleSubmit } = useForm();
// 2.
const onSubmit = (data) => {
console.log(data);
addReview(data);
};
// function to make a POST req to the server to insert data to MySQL db
const addReview = (data) => {
axios.post("http://localhost:3000/reviews", data).then(() => {
// 4.
props.setReviews([...props.reviews, {data}]);
});
};
}
And then, create the appropriate HTML form in the return function like the example below:
Import this component into App.js
and include it like so:
<Add reviews={reviews} setReviews={setReviews} />
Step 4: Update Reviews
We are now able to Create and Read from our MySQL database. Let's work on the Update next.
Create a Edit.js
file, a component that returns a form which a user can submit to update values of a specific review data.
To allow the user to update an existing review, we will:
- Import the necessary packages to
Edit.js
- Initialize our React form
- Create a function to update our database when the form is submitted
- Update our
reviews
array
// 1.
import { useForm } from "react-hook-form";
import axios from "axios";
export default function Edit(props) {
// 2.
const { register, handleSubmit } = useForm();
// 3.
const onSubmit = (data) => {
console.log(data); //{book_review: ..., book_rating: ...}
data["id"] = props.id; //add the id from props
updateReview(data);
};
// This will update existing data with new submitted values
const updateReview = (data) => {
axios.put("http://localhost:3000/reviews", data).then((res) => {
// 4.
props.setReviews(
props.reviews.map((item) => {
return item.id === props.id? {
id: item.id,
book_title: item.book_title,
book_review: item.book_review,
book_rating: item.book_rating,
}
: item;
})
);
});
};
Then, create a simple form in the return function and add the Edit
component in App.js
.
Add it inside our <div className="reviews">
and remember to pass in id
as item.id
as attributes from our Edit component to work.
<div className="reviews">
{reviews.map((item) => {
return (
<div className="review">
<h3>Title: {item.book_title}</h3>
<h3>Review: {item.book_review}</h3>
<h3>Rating: {item.book_rating}</h3>
{/*Add Edit here*/}
<Edit id={item.id} reviews={reviews} setReviews={setReviews} />
</div>
);
})}
</div>
The result will look like this.
Step 5: Delete Reviews
Finally, our Delete operation will be the simplest of all. Our client just needs to provide the id
of the review to delete from the database.
The request URL will contain the id
as params like: http://localhost:3000/:id
So to do this, create a Delete.js
file and proceed as follows:
- Import axios
- Create function to delete a review where
:id
in the URL isprops.id
- Update reviews array
- Create the delete button in return
// 1.
import axios from "axios";
export default function Delete(props) {
// 2.
const deleteReview = () => {
axios.delete(`http://localhost:3000/reviews/${props.id}`).then((res) => {
// 3.
props.setReviews(props.reviews.filter((item) => {
return item.id !== props.id;
})
);
});
};
// 4.
return (
<button className="del-btn" onClick={deleteReview}>
Delete Review
</button>
);
}
As usual, import this component to App.js
and insert it below our Edit component. Remember to include the relevant attributes to pass as props for Delete to work.
<div className="review">
<h3>Title: {item.book_title}</h3>
<h3>Review: {item.book_review}</h3>
<h3>Rating: {item.book_rating}</h3>
<Edit id={item.id} reviews={reviews} setReviews={setReviews} />
{/*Add Delete here*/}
<Delete id={item.id} reviews={reviews} setReviews={setReviews} />
</div>
Final result
And now, we should have a simple React app that performs the CRUD operations with our MySQL database!
Thanks for reading! We have finally completed our app but what's next? It's deploying it! In the next part of this series, let's learn how to deploy our full-stack React app to Heroku.
If this series has been helpful so far, do give this article a like or share and stay tuned for the next one. Cheers!