{"id":24018672,"url":"https://github.com/ryancoll/comp-3330-week5","last_synced_at":"2026-06-19T09:32:15.707Z","repository":{"id":139649191,"uuid":"415414426","full_name":"RyanColl/COMP-3330-week5","owner":"RyanColl","description":null,"archived":false,"fork":false,"pushed_at":"2021-10-15T17:58:37.000Z","size":407,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-25T21:35:19.304Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RyanColl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-09T20:24:45.000Z","updated_at":"2021-10-15T17:58:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"9c256dc4-19a6-4566-b8d0-d0612edf4b16","html_url":"https://github.com/RyanColl/COMP-3330-week5","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/RyanColl/COMP-3330-week5","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RyanColl%2FCOMP-3330-week5","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RyanColl%2FCOMP-3330-week5/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RyanColl%2FCOMP-3330-week5/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RyanColl%2FCOMP-3330-week5/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RyanColl","download_url":"https://codeload.github.com/RyanColl/COMP-3330-week5/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RyanColl%2FCOMP-3330-week5/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34526065,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-08T10:17:34.934Z","updated_at":"2026-06-19T09:32:15.701Z","avatar_url":"https://github.com/RyanColl.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# COMP-3330-week5\n## Express | Mongoose | React | Redux\n\nLast week we didn't have any homework sessions, but we did cover NodeJS as a backend language, alongside express. This week, we take this knowledge further and build a backend RESTful API. This involves following a set of rules prescribed by each method. The methods are: PUT, PATCH, POST, GET, and DELETE. I am going to take this a step further and create a react app using redux. I will display the data from the database, and allow us to directly delete from the database each user. We could add edit and add buttons, but we don't need to.\n\n## HTTP Methods\n\nWhen trying to reach the server, use Postman and enter http://localhost:3000/api/users into the bar. Use the GET, POST methods to call on the api url. Use GET, PUT, PATCH, and DELETE on the url with the id added to it. For example, after using Postman to send a GET request to the url, copy the ID and place it at the end of the url, like this: http://localhost:3000/api/users/placetheidhere , then use GET, PUT, PATCH or DELETE.\n\n#### DELETE \nDelete is for deleting a resource. When we send a delete request to the express server, the server respondes by taking the id as a parameter, and deleting the user entry with the same id.\n\n#### PATCH\nPatch is similar to PUT in the sense that you are modifying existing data. Patch, however, takes in both an id and a new piece of data. It finds the user with the same id, and replaces the piece of data inside it with the new piece.\n\n#### PUT\nPut is similar to PATCH, but instead of going into an entry and mutating a piece of data, PUT replaces the entire object, keeping the same id.\n\n#### POST\nPost is used for adding new pieces of data to the database. You cannot actually POST on http://localhost:3000/api/users/placetheidhere because it doesnt make sense. You want to create new pieces of data with POST, therefore sending it to the http://localhost:3000/api/users url makes sense. Follow this with a GET request to see the new entry.\n\n#### GET \nGET is similar to its word; it gets a requested resource. The server returns the list of users with a get request. The server will also give you the user if you use a GET request on this url: http://localhost:3000/api/users/placetheidhere .\n\n## Command Scripts\n1. \"build\": \"react-scripts build\",\n2. \"launch\": \"npm run build \u0026\u0026 node Server.js\"\n\nThe build script is important when blending react and express. The build script builds my react app into the build folder for my express app to host. The launch script builds the app and then launches the server. It is essential that when working like this you rebuild your react app every time you host, or your changes will not show up.\n\n## Mongoose\n\nMongoDB and Mongoose go hand in hand to create models for your database entries. This gives you fast and easy queries while preserving safety in the form of data manipulation. When we create these models we must imagine the shape of our documents and model them out. For example, each user has a first_name, a last_name, a profession, and a hasDegree variable which is boolean, indicating whether the user has a degree or not. We use the following code to model a user:\n\n#### userModel.js\n```js\nconst mongoose = require(\"mongoose\");\nconst {Schema} = mongoose;\nconst userModel = new Schema({\n  first_name: {type: String},\n  last_name: {type: String},\n  profession: {type: String},\n  hasDegree: {type: Boolean, default: false},\n});\nmodule.exports = mongoose.model(\"User\", userModel);\n```\n\n## How it Works\nIt works by first accessing a database that has predefined users, and hosting a server that has numerous methods for accepting requests. I use two routes, one for the /api/books, and one for the /api/books/:bookid. The api/books route has two methods, GET, for getting a list of all the users, and POST, for sending data as a new database entry. The api/books/:bookid has four methods: GET, PUT, PATCH, DELETE. The GET gets the information about that specific user, the PUT takes in new user data and replaces that specific user with it, the PATCH takes in a piece of information and replaces the specific user data that matches the input data. The DELETE method seems obvious... it deletes the object whos id it matches.\n\nI have created a frontend. As you know the react app will be hosted naturally through the build folder as express runs itself as a server. Express will still respond with json through the browser or as json through postman when requests are sent to its url. The added react app uses fetch to access the api in the express app, this gives me the array of users from mongo, which is then added to redux and attached to the state variable. These users are printed out to the page, with an extended delete functionality. This will permanently delete that user by using fetch to access the delete request for that specific ID. To add more users, use Postman.\n\n## Redux\n\nReact Redux gives us more capability with state because we can make our state into a store that is accessible throughout all of the app. I used redux with react on the frontend to send a fetch request to my server, and store the value via: \n```js\nconst fetchUsers = () =\u003e {\n    fetch('/api/users')\n      .then(res =\u003e res.json())\n      .then(data =\u003e {\n        store.dispatch(actions.getUsers(data))\n      })\n      .catch(err =\u003e setErrMsg(err))\n  }\n```\nThis takes in our data inside of the promise and sends it to store. The state becomes an array of users. The dispatch event calls the subscribe method, which is used to update the state in the react app. \n```js\nReact.useEffect(() =\u003e {\n    store.subscribe(() =\u003e {\n      setUsers(store.getState())\n    })\n  })\n```\nThis updates the state of the react app by updating the users variable with the user array from store. This way, if we change the store anywhere, the subscribe method will run, and change our state everywhere. The goal of our app is to display the users using a get request. Now that we have our data, we want to render it. Use effect gives us the ability to run asyncronous tasks. We use the use effects to place the data into the array. The app will still load before that, so we use the \u003cb\u003e\u0026\u0026\u003c/b\u003e operator to check a condition before loading. \n```jsx\n{users !== [] \u0026\u0026 users.map(user =\u003e {\n            {console.log(user.hasDegree)}\n            return (\u003cdiv style={{width: 300, height: 180, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'space-evenly', padding: 15}}\u003e\n              \u003cp style={{color: 'white', margin: 0, padding: 0}}\u003e{user._id}\u003c/p\u003e\n              \u003cp style={{color: 'white', margin: 0, padding: 0}}\u003e{user.first_name}\u003c/p\u003e\n              \u003cp style={{color: 'white', margin: 0, padding: 0}}\u003e{user.last_name}\u003c/p\u003e\n              \u003cp style={{color: 'white', margin: 0, padding: 0}}\u003e{user.profession}\u003c/p\u003e\n              \u003cp style={{color: 'white', margin: 0, padding: 0}}\u003eHas a Degree: {`${user.hasDegree}`}\u003c/p\u003e\n              \u003cdiv style={{width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-evenly'}} className='links'\u003e\n                  \u003cbutton onClick={() =\u003e {deleteUser(user._id)}} style={{backgroundColor: 'rgba(0, 0, 0, 0)', color: 'white'}}\u003edelete\u003c/button\u003e\n              \u003c/div\u003e\n            \u003c/div\u003e)\n          })}\n```\nIf we do not check the condition, then our react app will try to build the structure above when the array is empty. This will crash our app. Using ternaries to check conditions before rendering is good practice.\nFor every user made, a delete button is made as well that takes in the id of the user and removes it from our state via deleteUser:\n```js\nconst deleteUser = (id) =\u003e {\n      fetch(`/api/users/${id}`, {\n        method: 'DELETE'\n      })\n      let newUsers = users.filter(user =\u003e user._id !== id)\n      store.dispatch(actions.getUsers(newUsers))\n}\n```\nBecause its mongodb, the user id is _id. This is a good example of a nodejs RESTApi that also hosts a react app that communicates with it.\n\n## ES6\n\nDefault from line 4 of reducer.js:\n```js\nexport default function reducer(state = [], action)\n```\n\nConst and Let from lines 25-32 of App.js:\n```js\nconst deleteUser = (id) =\u003e {\n      fetch(`/api/users/${id}`, {\n        method: 'DELETE'\n      })\n      let newUsers = users.filter(user =\u003e user._id !== id)\n      store.dispatch(actions.getUsers(newUsers))\n  }\n```\n\nTemplate Literal String from line 44 of App.js:\n```js\n`Has a Degree: {`${user.hasDegree}`}`\n```\n\nDestructuring from line 7 of App.js:\n```js\nconst [users, setUsers] = React.useState([])\u003c\n```\n\nArrow function from lines 17-19 of App.js: \n```js\nReact.useEffect(() =\u003e {\n    fetchUsers()\n  }, [])\n```\n\nSpread syntax from line 8 of reducer.js:\n```js\n...action.payload.users\n```\n\nModules from lines 1-4 of App.js:\n```js\nimport React from 'react'\nimport './App.css';\nimport store from \"./Redux/customizedStore\";\nimport * as actions from \"./Redux/actions\";\n```\n\nPromises from lines 10-15 of App.js:\n```js\nfetch('/api/users')\n      .then(res =\u003e res.json())\n      .then(data =\u003e {\n        store.dispatch(actions.getUsers(data))\n      })\n      .catch(err =\u003e setErrMsg(err))\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryancoll%2Fcomp-3330-week5","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryancoll%2Fcomp-3330-week5","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryancoll%2Fcomp-3330-week5/lists"}