DEV Community

Cover image for My Final Project - Built With React, Redux, and Rails
Brittany
Brittany

Posted on

My Final Project - Built With React, Redux, and Rails

OH MY GOODNESS! I actually did it! I completed my final project for the Flatiron School Software Engineering Program and I can officially call myself a Full Stack Software Engineer!

My final project idea was a simple one, or so I thought. I wanted to create a music diary. What is a Music Diary you may ask? Well, I love music and there are times when I just want to write about my feelings for the day and why a particular song resonated with me. So I thought it would be cool to create an application where a user could create a diary entry for the day associated with a song found using the Spotify API. In addition, I wanted users to be able to comment on other users diary entries. As always, I drew out my project idea:

Alt Text

Creating the idea was hard because I could not come up with the best idea this time. I knew I wanted to create something associated with music and wanted to attempt using an API (Spotify). Once I came up with an idea I had to really concentrate on how to use Redux with React.

My Error Handling method using Redux and React.

For starters, in my backend I wanted to make sure that a user could not add multiple diary entries for the same day. In order to do that I added the following to my Entry model:

class Entry < ApplicationRecord
    belongs_to :user
    belongs_to :song
    has_many :comments, dependent: :destroy

    validates :date, presence: true
    validates :description, presence: true

    validates_uniqueness_of :date, :scope => :user_id

end
Enter fullscreen mode Exit fullscreen mode

The above validates the date to make sure that it is unique to the user_id. So the same user_id can not have the same date.

Then I moved on to my frontend and created an errors reducer like so:

export default function errorReducer(state = {message: "" }, action) {
    switch (action.type) {
        case "ADD_ERROR":
            return {
                ...state,
                message: action.message
            }
     case "REMOVE_ERROR":
                return {
                  state: {message: "" }
                }
        default:
            return state
    }
}
Enter fullscreen mode Exit fullscreen mode

The error reducer is pretty straight forward. It has a state that holds message which is a string by default and I wanted to be able to remove the error message so I created the action "remove_error" for that. I imported the errors reducer into the root reducer.

import { combineReducers } from "redux";
import commentsReducer from "./commentsReducer";
import searchReducer from "./searchReducer";
import userReducer from './userReducer'
import addSongReducer from './currentSongReducer'
import EntryReducer from './entryReducer'
import entriesReducer from './entriesReducer'
import loadingReducer from './loadingReducer'
import errorsReducer from './errorReducer'



const appReducer = combineReducers({
  user: userReducer,
  song: addSongReducer,
  search: searchReducer,
  comments: commentsReducer,
  entries: entriesReducer, 
  entry_id: EntryReducer,
  loading: loadingReducer,
  errors: errorsReducer,
});

export default rootReducer;
Enter fullscreen mode Exit fullscreen mode

Now my errors will be accessible in my redux library under errors. I added an if statement to my action creator:

export const songOfTheDay = (song) => {
  return dispatch => {
    // dispatch({ type: 'REMOVE_RESULTS' })
    fetch(API + "/entries", {
      method: 'POST', 
      headers: {
        'content-type': 'application/json'
      },
      body: JSON.stringify({song: song}),
    })
    .then(response => response.json())
    .then(results => {
       if (!results.errors) {
        dispatch({ type: 'REMOVE_ERROR' })
        dispatch({ type: 'SONG_RESULTS', results })
        } else {
        dispatch({ type: 'ADD_ERROR', message: results.errors })
     }
  })
  }
}
Enter fullscreen mode Exit fullscreen mode

The if statement above states that if there are no error messages it will remove any existing errors from the state and add the results to the song.

The if statement checks to see if the results returned comes back with an error. It will add the message errors to the errors state.

Then I added the following to my component:

const SelectedSong = (props) => {
 if(!props.errors){
  return(
     <div className="card">
           card information here 
    </div>
  )}
  else {
    return(
    <div>
      <p> This is props</p>
      <p> {props.errors} </p>
    </div>
    )
  }
}

const msp = (state) => ({
    errors: state.errors.message
  })

export default connect(msp, null)(SelectedSong)
Enter fullscreen mode Exit fullscreen mode

The above checks to see if there are any error messages using the map state to props. If there are no errors it will continue to show the card information, else it will display the prop errors.

There is always a better way of doing something but it worked for my situation and what I needed to get done.

As always, thank you for reading!

Sincerely,
Brittany

Oldest comments (0)