Creating a Content/Entertainment Tracking App with React
Tags: react, ruby, redux, webdev
Published: 2022-01-04 17:30:08

I've just wrapped up my latest project: a content tracking application that used React, Redux, and a Rails API to persist the user-inputted data. The objective of this project was to create a single-page application using these technologies. Here is a link to the [frontend repository](https://github.com/atcarter/contenttracker-frontend) as well as the [backend repository](https://github.com/atcarter/contenttrackerbackend). To try out the application yourself, simply clone both repositories to your machine, run `bundle install`, start the rails server with `rails s`, and run `npm install && start` on the frontend.

###Project Planning

I decided to go with a content/entertainment tracking app because it was similar to previous projects and would allow me to focus on how the technologies differed/improved. I started by brainstorming how I wanted to set up my backend (mainly what the models would look like). While outlining my backend, I was also thinking about the components that I was going to have in my React app. I came up with a rough list, as well as a sketch on how I wanted them to look on the page. Since I was using Redux to manage the state of my application, I also thought about which components I was going to have to connect to the store and how.

###Implementation
To create the rails backend, I created a new rails project using the `--api` flag. I used the resource generator to create the skeleton of what I needed to handle content and reviews in rails. To protect the data on the server side, I added validations to both my Content and Review models. For example, used a method to persist content titles and types in title case. For reviews, I used a validation to make sure that the rating was between 1 and 5. In thinking about the future fetch request I was going to send to my backend to retrieve my seed data, I used the Active Model Serializers gem to send my object associations in JSON. I later removed the associations but I'll talk about this later.

After wrapping up my backend, I created my frontend application using `create-react-app`. First, I installed the majority of the libraries I needed for this project: Redux, React-Router, and Redux-Thunk. Then, I focused on building my actions, reducer, and dispatch since this part was the trickiest for me. Initially I attempted to normalize my database structure in my Redux store however I found that my new state objects weren't being created properly. I then decided to separate my reducer and actions and use the `combineReducers` method from Redux. I used hooks where I could because I found they made the process easier; I even added the `react-hook-form` library to render both forms in my application. I had separate components for my About page, the Nav Bar, Content List, Content, Review List, Review, and a component for each of the forms. This was a single-page application but I still tried to stick to RESTful routing where it made sense. I used `react-router` to mimic this convention on the client side. For example, clicking on the New Review link under one of the content would take you to "/contents/1/review/new". I usually waited to test my app's functionality after I completed all of the pieces that were needed to complete a particular action.

###Roadblocks and Struggles

While programming this application, I ran into a few roadblocks that left me stumped. I used a combination of my notes, official documentation, and Google to resolve the problems I ran into. For example, after having a hard time organizing my store, I used the `combineReducers` function from Redux. After I fetched my data, I was having a hard time adding it to the store until I realized that I was misusing the spread operator. Having the backend open whenever I made calls to my rails API was incredibly informative when I was testing my GET, POST, and DELETE calls. Moving forward, I hope to clean up the presentation of the app. I'd like to try using a UI library that could help it look more presentable than the minimal CSS I've added.