Floatpad

project / April 20th, 2021

Floatpad Home Page

GitHub

Background

The Floatpad is a simple single-page MERN stack web app that allows users to write and post notes for display on the page. Each posted note has a title, written content, and a button to delete the note.

Initially, the Complete Web Development 2021 Bootcamp taught me to build this app with only a front end with React, and therefore it lacked the ability to persist data after the Express server restarted. After I completed the Fitboard MERN stack project and learned how to connect the front end to the back end, I applied this new-found knowledge to the Floatpad to enable it to persist data.

Purpose

Originally, this app was built to introduce the basics of the React front-end framework and learn how React components can be reused to simplify the structure of a user interface in a web app. Before building the app, a series of topics and exercises are covered. This includes the Babel JavaScript compiler inside React and how it converts HTML code in a JavaScript file (JSX) into plain JavaScript, template literals and how they can be used to insert JavaScript expressions in HTML code, and styling React elements. After the app began development, I also learned about React props, mapping data to components with the Map, FIlter, and Reduce methods, JavaScript arrow functions, conditional rendering using the ternary operator and AND operator, state in React, React Hooks and the useState function, functional components, destructuring objects and arrays, the JavaScript spread operator, and managing the component tree.

After the initial version of Floatpad was completed, I learned about MERN stack development through building the Fitboard app. I then circled back to the Floatpad project and sought to apply what I learned about connecting an Express server to a React app using Axios, in order to allow the app to retain data and make the project feel complete. Building this version of the Floatpad allowed me to reinforce the concepts I learned about organizing the back end and front end files before connecting them. Unlike the Fitboard, the Floatpad tested these concepts with using React functional components.

Concepts and Tools Used

  • React - JSX, template literals in ES6, styling, props, mapping data, functional components, conditional rendering, event handling, React state and hooks, component tree

  • JavaScript arrow functions, using JavaScript expressions in HTML code and HTML code in JavaScript, destructuring objects and arrays, the spread operator

  • MERN stack development

  • MongoDB and Mongoose

  • Express.js

  • Node.js

  • Axios

  • Material-UI

Scope and Modifications Made

As previously stated in the background section, this app originally only contained a front end and lacked the ability to persist data and retain the notes that were posted after restarting Express server. After learning about MERN stack development and building the Fitboard app, I expanded the Floatpad app to contain a back-end and allow it to retain posted notes. Since the focus was primarily on learning React, most of CSS styling was provided by the bootcamp. I later modified it to achieve the desired look.

Process

Part 1: Original Version

After completing exercises to learn about converting HTML code in a JavaScript file (JSX) into plain JavaScript and vice versa, I learned to how to set up a local environment for React development and create a React app. After this, I created a Header component to render the Floatpad name and a Note component to render a div element with a title and content. These components are then imported to the main App component and modified to have CSS styles applied to them.

Once the foundation of the app is built, exercises are completed to learn about React props, React DevTools, mapping and filtering data to components, and JavaScript arrow functions. The map method is then applied to loop through an array of notes and create props for the Note component. Each note is then rendered as a separate Note component on the page with their own title and content. This completes the second step.

Finally, exercises on the ternary, AND, and spread operators, the React useState hook, JavaScript object and array destructuring, event handling, and state management are done. This is applied to the final step of building the original version of the app, which is to implement the add note and delete note functionalities.

To add notes, a stateful constant (an object) is created in the CreateArea component (which is the note creation area) to keep track of the title and content of each note (which are properties of that object). The forms responsible for collecting the note title and content from the user in the creation area are then assigned functions that will update the title and content of the stateful note when triggered. This newly updated note is passed to the main App component through the use of props - the prop passed down to the creation area enables the add button (which is in the CreateArea component) to trigger the function to add this newly updated note (which is in a different component, the App component). The note is then added to an array (which also has state) in App that will update every time a new note is added. Finally, a map function is used to loop through this new array of notes and render each note as a separate Note component below the creation area.

To delete notes, each Note component will have a delete button that will activate a delete function in the App component when clicked. Again, this function is passed to each Note component through the use of props. This function will take the ID of the deleted note, access the previous state of the notes array, and use the filter function to remove the note with the matching ID before rendering the notes array again.

Finishing touches are made by using the Material-UI React library to add pre-made React components like an plus-shaped icon to the creation area. Instead of the word "Add", the add button will use this icon instead. A trash bin icon is also added to each posted Note to act as the delete button, instead of the word "Delete". Material-UI is also used to add animations to the new add button, like a colour change (when the mouse hovers over it) and a zoom effect (when the Floatpad page is rendered). The state of the CreateArea is also tracked to see if its currently expanded or not. Through conditional rendering, a function is written to check if the creation area is clicked or not. If clicked, the creation area will fully expand to include the form for the title and the add button. Otherwise, the creation area will be more compact and only show the form for content.

Part 2: MERN Stack Version

The files pertaining to the React app are moved into a folder called "client". Outside "client" is where the Express server is created by initializing an NPM package. Mongoose is used inside the server file to create a database and establish a connection to MongoDB Atlas. A collection of notes is then formed inside the database after creating a note model. A router file with API endpoint routes to GET the notes in the database, POST them, and DELETE them is created and added to the server file.

Just like how the Fitboard ExercisesList component used the componentDidMount React lifecycle method to load the existing list of exercises from its database before the page is rendered, the Floatpad uses the React hook useEffect in its App component to load the list of existing notes to its home page. In both cases, Axios is used to make a GET request to the correct endpoint route. The state of the notes array is then updated to included all existing notes. An Axios DELETE request is included in the delete function of App to remove a deleted note from the database, and not just from the array of notes to be rendered. In the CreateArea component, an Axios POST request is added to the function responsible for adding notes. This ensures a new note is added to the database and not just the array of notes to be rendered.

Once completed, a test is done to ensure that the app is pulling the correct data from the notes database and persisting it after the Express server restarts.

Outcome and Takeaways

The React module was the last and longest module in the Complete 2021 Web Development Bootcamp, and contained some of the most difficult material to learn in the course. It took time to grasp the concepts of state and managing state using hooks. I found that using class components and lifecycle methods like componentDidMount in the Fitboard project helped me better understand a React hook like useEffect and its role with functional components in Floatpad, since they were analogous to each other and served the same purpose.

The biggest takeaway after completing the Fitboard and Floatpad projects were that the most difficult part of MERN stack is actually deploying the app. After completing the Fitboard project (which had the back end as a subdirectory and the front end in the root directory) and realizing that Heroku could not run the Express server and React app, I tried a few different file structures for the Floatpad app. This included having the front end (in a folder called "client") and back end (in a folder called "server") as separate subdirectories, and the front end as a subdirectory and the back end in the root folder (which was the latest structure I tried). In all cases, I also tried adding scripts like the "heroku-postbuild" script to the server package.json file in order to serve static files from the front end to Heroku and build the app, but all attempts have resulted in Heroku rejecting the app and not building it. I have also tried reading the Heroku build logs, watching several articles and videos on MERN stack app deployment, and re-creating the app from scratch but none of these solutions have worked. In the future, I would like to explore services other than Heroku for hosting MERN stack apps, or see if I have to use a combination of Heroku and another service in order for deployment to work.

Possible Improvements Going Forward

Similar to the To-do List, the Floatpad would benefit from adding a collection of users, along with authentication and security to enable users to log into their own account where they can access their own notes. Currently, the notes posted on Floatpad can be read by anyone, essentially making it only for "public" use.

A possible solution for this issue would be to simply deploy the original version of Floatpad, which has the same functionality and no back end. The trade-off with this idea is that it would only be for "temporary" short-term use to jot down quick notes and map out brief ideas for brainstorming, with no expectation of keeping them after closing the browser. To keep them, they would have to be written down on paper or saved in a document with a text editor before closing the app.

It would also be helpful to add an option to edit the title and content of existing notes, or give the user an option to dynamically create different pages that will contain different sets of notes.


External Link

Because Heroku cannot run the Express server and React app (which are in separate directories) at the same time, I cannot deploy this app for the time being. I have spent a lot of time researching and trying numerous solutions (the most common adding a heroku-postbuild script to serve the static files to Heroku and build the project), but have none have worked so far. When I have time, I would like to try deploying this app again.

In the meantime, anyone who is interested in exploring the app locally can follow the instructions below.

Instructions for Running Locally

  1. Clone the GitHub repository in the above link

  2. Go to the root directory of the project folder in a terminal using the cd command

  3. Install all project dependencies for the back end with:

    'npm install'

  4. Use the cd command to enter the client folder inside the project directory

  5. Install all project dependencies for the front end with:

    'npm install'

  6. Install the nodemon utility globally with:

    'npm install -g nodemon'

  7. In your terminal, open another tab and cd to the root directory of the project. Run the Express server by entering the following command:

    'nodemon server.js'

  8. In your original tab, run the React app in the client directory by entering:

    'npm start'