# Track Podcasts on Spotify w/ React/ Redux + Rails

# Project Intro
For my fifth and final project at the Flatiron School, I decided to create a podcast tracker application that lets a user view, add and delete podcasts. Each podcasts has properties such as a name and a link to the podcast itself. The project is specifically titled "spotify-podcast-react-redux-project" on the [repo](https://github.com/Dusch4593/spotify-podcast-react-redux-project) because the seeded podcast data all contain Spotify links. I also intend on building off of this application in the near future by incorporating Spotify's [new batch of podcast API endpoints.](https://developer.spotify.com/community/news/2020/03/20/introducing-podcasts-api/) 

# Technologies Used
Like my previous project, the frontend and backend belong in their own separate repositories and are both housed under the  [main project repo](https://github.com/Dusch4593/spotify-podcast-react-redux-project) . 
### Frontend
I was tasked with creating a React application that is connected to a Redux store. Despite it being a single-page application, I went with  [react-router's] (https://reactrouter.com/core/guides/quick-start)  `<BrowserRouter />`, `<Switch />`, and `<Route />` components: 

```
// ...frontend/src/App.js

import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'

class App extends Component {
  render() {
    return (
      <Router>
        <div className="main-container">
          <Switch>
            <Route exact path="/" component={ Home } />
            <Route exact path="/podcasts/new" component={ PodcastsNew } />
            <Route exact path="/podcasts" component={ Podcasts } />
          </Switch>
        </div>
      </Router>
    )
}
}
```

Because the application state will be handled by a Redux store, I added a `src/actions` and `src/reducers` folder to house files whose job is to create actions and return an updated version of the state. 

The actions I created were: 

```
{type: "GET_PODCASTS", payload: podcast} //=> fetches the current state (the list of podcasts)
{type: "ADD_PODCAST", payload: podcast} //=> adds a podcast to the state ( becomes POST request to backend)
{type: "REMOVE_PODCAST", payload: podcast} //=> deletes a podcast from the database, removing it from the frontend (DELETE request)
```
### Backend
As with some of my previous projects, I built the backend of the application in Rails (using the `--api` flag to skip creating view files -- just the "MC" part of "MVC" ;) ).

```
# in the backend repo

rails new spotify-podcast-react-redux-project --api
```

For the most part, there isn't a lot of code that was written on this end. Most of the work was done in the `podcasts_controller`, where requests from the frontend will go to be handled by the appropriate controller action. 

```
class PodcastsController < ApplicationController
  before_action :set_podcast, only: [:show, :update, :destroy]
  def index
    @podcasts = Podcast.all
    render json: @podcasts
  end

  def show
    render json: @podcast
  end

  def create
    @new_podcast = Podcast.new(podcast_params)

    if @new_podcast.save
      render json: @new_podcast
    else
      render json: @new_podcast.errors
    end
  end

  def destroy

    @podcast.destroy
    render json: @podcast
  end

  private
  def set_podcast
    @podcast = Podcast.find_by_id(params[:id])
  end

  def podcast_params
    params.require(:podcast).permit(:name, :hosts, :genres, :link)
  end

end
```

# Challenges Faced
## Understanding React-Redux State-Flow
As  [famously noted](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367) , Redux can often be more of a burden for developers than a blessing. This is especially true of smaller, simpler applications and ***especially*** ones that are already fetching data from a backend API. 

Despite how superfluous this may seem, the point of this project was for me to demonstrate my knowledge of React-Redux state-flow (just with Rails thrown in the mix!). 

Essentially, react-redux state-flow is unidirectional in nature; the parent React component passes down it's store-accessed information to it's child components as props. Those children can then work with those props to render data in interesting ways. The "redux" part of the state-data flow is essentially this: **Action ==> Reducer ==> New State**. 

Regardless of what technology Redux is paired with (even React), it always follows this flow. **Actions** are dispatched to the Redux store, where a shallow copy of the old state and an updated version of the state are merged or **reduced**, which then returns the **new state** (and thereby updating the store). 

## Asynchronous Programming w/ Redux Thunk
Another challenge for me was understanding the inner workings of  [Redux Thunk](https://github.com/reduxjs/redux-thunk). 

One of those unavoidable parts of programming is  [asynchrony](https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)).  

In the context of a React-Redux application, in the `src/actions/index.js` file, it isn't enough to simply return an object with the action information (`type` and `payload`). Instead, thank in large part to the Thunk middleware, we can return a callback function that: 

1. Makes an AJAX fetch request (like `GET` or `POST`)
2. Doesn't return anything until the fetched Promise object is resolved
3. Returns a dispatched action with the action object passed in

Even after this project, I'm still not feeling too confident with async programming. However, I definitely feel good about ultimately getting it to work in this project. 

If you'd like to check out the project for yourself, clone the  [repo](https://github.com/Dusch4593/spotify-podcast-react-redux-project)  and enjoy! 

Happy Coding, 
Brandon


# Resources
 [Asynchronous Programming](https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)) 

 [React Router](https://reactrouter.com/core/guides/quick-start) 

 [You Might Not Need Redux (Medium article by Dan Abramov)](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367) 


