Notes on creating Node Express & MongoDB (simple) Blog API and refactoring React tutorial Blog App to use it
Note: This post is a details-post for the post: Learning web app development through free online tutorials – Organized Notes and Log, https://raviswdev.blogspot.com/2024/03/learning-web-app-development-through.html .
This post is based on a detailed note-cum-log I wrote as I was creating the Node Express & MongoDB tutorial Blog API. I think it may be useful for others who are using the roadmap to full stack web development that I have provided.
The steps I followed to successfully create a Node Express & Mongo DB tutorial Blog API which worked with the React tutorial Blog application after some small changes to the latter, are given below:
- I created a project with only the latest version files of my coding variation of the Node Express tutorial's 1st project (TASK MANAGER). I tested it and it was working. I saved this project excluding node_modules as a separate folder which can act as a project starter folder/boilerplate for ***simple (tutorial grade)*** Node Express backends. Note that this project includes a Mongoose, mongoDB, morgan logger, asyncwrapper, custom error handling etc. are all included. However, the code involved is typically not long or complex, except for asyncwrapper (which I find to be complex). But then asyncwrapper perhaps can simply be used as is, even if one only understands how to use it but not how exactly it works.
- Refactored the starter project code to use post/posts/Post instead of person/people/Person, and (post) title instead of name. VSCode's feature of search and replace in files in project was very helpful for this task, though a few had to be handled manually. Also had to change filenames in project from person to post. Was able to refactor the frontend code too though it required more manual work but not too much work. MongoDB Database is still "People-Manager" but has two collections: people and posts. The refactored project data uses posts. I think creating a new MongoDB database like "Blog" and having posts collection within it may involve simple step in MongoDB to create the "Blog" database and in .env file in the project, I will need to use "Blog" instead of "People-Manager" for MONGO_URI env. var. Right now creating new database "Blog" is NOT a priority.
- Added to mongoose models schema (model/post.js) to bring it in sync with data/db.json of cawv-1201-blog-easyPeasy React project. The new schema is as follows:
- To add body and datetime functionality to app code, only controllers/post.js had to be modified. Within post.js, getPosts, getPost and deletePost did not have to be modified. Only createPost and updatePost had to be modified. Note that the app does not support patch API now. Updates are done through put API (routes/post.js sets up updatePost method in controllers/post.js as the function to 'handle' put API). Following changes were made to createPost (in controllers/post.js):
- Following changes were made to updatePost (in controllers/post.js):
- Next task was to modify the React Blog app. to use above Node Express API instead of json-server. Used source code of my code variation of the React tutorial easy-peasy project as the base. Ran 'npm install' to create node_modules. Removed not needed packages from it using uninstall. Got the React app to run and it worked as expected using json-server data. Changes to be made in refactoring this app to use Node Express API:
- Blog API returns posts as data property in return object whereas JSON server returns posts directly. So React app code will have to refer to axios Response.data.data to get the posts or post data.
- The id property of JSON server version has to be replaced by _id property of Blog API version
- patch API usage has to be changed to use put API
- API url has to be changed to refer to Blog API
- Made some of the above changes. Ran app. React 'npm start' prompted for port change from 4000 as 4000 was being used (by Express API server). I said yes and React used port 4001. Got this error (on browser console), "Access to XMLHttpRequest at 'http://localhost:4000/api/posts/' from origin 'http://localhost:4001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource." which resulted in further errors. My useEffects code in app.js of React app had some bugs related to error handling. Fixed those bugs and later refactored the useEffects code to make it cleaner. Am not including those details here as they are not related to this post's topic.
- Got the solution for the CORS error from https://www.geeksforgeeks.org/how-to-deal-with-cors-error-in-express-node-js-project/ . The added code to app.js in express API that fixed it (with some earlier code for context):
- The React app code expects post objects to have all properties (including body). So added a default of "" for body in model/post.js in Express API. Then React app was able to retrieve the two posts from express API. Viewing post was OK.
- Got React app's new post to work quite easily (just one code line had not been refactored; to use axiosResponse.data.data instead of axiosResponse.data).
- React app's delete post worked straight away.
- React app's edit post needed code to be changed to use put instead of patch and some other refactoring (to use axiosResponse.data.data instead of axiosResponse.data). Then React app's edit post functionality also was working.
- Now all functionality of React app was working with Node Express API. I then dropped the json-server package and data directory from the project. Also cleaned up some commented old code. Tested app again and it was working.
const schema = new mongoose.Schema({ title: { type: String, required: [true, "title has to be specified"], trim: true, }, body: { type: String, }, datetime: { type: Date, default: Date.now }, });With only above schema change, the app is working, including the front-end even though body property is not created when new posts are created. datetime property is created due to above default specification.
const { title, body, datetime } = req.body; ... const post = await Post.create({ title: title, body: body, datetime: datetime, });Note that earlier code for the above, did not have body and datetime properties. That was the change made. Tried out post API request through Postman, and it worked. MongoDB website shows it and Postman Get (all posts) shows it (body added via post is shown). A test case was if only title is provided in Postman post request. The API app adds a new document with _id, title and datetime properties (datetime set to current datetime) but without body property. Looking up the documentation to check if this is how Mongoose/MongoDB are supposed to work turned out to be a time-consuming task.
const post = await Post.findOneAndUpdate( { _id: postID }, { title: req.body.title, body: req.body.body, datetime: req.body.datetime }, { new: true, runValidators: true } );Note that earlier code for the above, did not have body and datetime properties. That was the change made. Tested through Postman and it worked.
const express = require("express"); const cors = require("cors"); const app = express(); // CORS is enabled for all origins app.use(cors());Ran 'npm install cors' and then ran the app. The CORS error did not come up.
That finished the task of creating Node Express & MongoDB tutorial Blog
API and refactoring the React tutorial blog app to work with it.
Comments
Post a Comment