React Fullstack Project for Flatiron
Tags: react, rails, webdev, javascript
Published: 2020-02-19 20:59:29

---
title: React Fullstack Project for Flatiron
published: true
description: 
tags: react, rails, webdev,javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/jvmz12pirg0x90zql5v2.jpg
---

## Introduction 

**Requirements**
* The code should be written in ES6 as much as possible 
* Use the create-react-app generator to start your project.
* Your app should have one HTML page to render your `react-redux` application using 2 container components, 5 stateless components, and 3 routes. 
* The Application must make use of `react-router` and proper **RESTful** routing
* Use Redux middleware to respond to and modify state change
* Make use of async actions to send data to and receive data from a server
* The Rails API should handle the data persistence and should be using `fetch` within your actions to GET and POST data from your API.
* Your client-side application should handle the display of data with minimal data manipulation. 
* The application should have some minimal styling: feel free to stick to a framework (like react-bootstrap), but if you want to write (additional) CSS yourself, go for it!

## App Design 

**React** - As per the direction, I used Create React App to setup the frontend project. 

**SIDEBAR**: I would rather have used my personal [React boilerplate project](https://github.com/eclectic-coding/react-parcel-boilerplate) using [ParcelJS](https://parceljs.org/), but that may be a topic for another article.   

FYI. This project is a redesign of a previous App for Flatiron utilizing Ruby on Rails only. You can read more about that project below.  

{% link https://dev.to/eclecticcoding/rails-movie-browser-project-2p05 %}



**Styling** - Most projects I have spun put pretty quickly and have relied on Component UI's to decrease the development time. I have used Bootstrap, and TailwindCSS and Bulma. Even though my preference would be to employ SCSS, I did not need to be distracted with Styling for this project, I utilized Bootstrap with [React-Bootstrap]().

**API** - For accessing the data I used the [MovieDB API](https://www.themoviedb.org/?language=en-US), which is a well documented API and was a joy to work with. There is a level of complexity of the JSON data from the API, which at times was challenging.  

## Fetching API 
As with the previous application, I used the RestClient gem to fetch the data, but because of the complexity of the JSON structure, I decided to seed the development DB: 

```ruby
movie_api = Rails.application.credentials.dig(:development, :movie_api)

n = 1
while n < 501
  movie_seed = JSON.parse(RestClient.get("https://api.themoviedb.org/3/movie/popular?api_key=#{movie_api}&page=#{n}"))
  movie_seed['results'].each do |movie|
    Movie.create(
      movie_id: movie['id'],
      title: movie['title'],
      release_date: movie['release_date'],
      poster_path: movie['poster_path'],
      backdrop_path: movie['backdrop_path'],
      overview: movie['overview'],
      average_vote: movie['vote_average'],
      popularity: movie['popularity'],
      budget: movie['budget'],
      tagline: movie['tagline'],
      runtime: movie['runtime'],
      genre_ids: movie['genre_ids']
    )
  end
  n += 1
end
```


## Movie Genres mapping 

One problem with the retrieved JSON data from the Movie API, was the way movie genres were su0plied. In the original call, for each movie, an array is supplied of genre id's, but no genre names. I stored these id's in an array in the Postgres DB.  

I made a second call to the Movie API using `curl` and saved the genre table, mapping id's to strings, to a JSON file which I converted to a JavaScript object to read from:  

```javascript
let genres = [
  {
    id: '28',
    name: 'Action'
  },
  {
    id: '12',
    name: 'Adventure'
  },
  {
    id: '16',
    name: 'Animation'
  },
  {
    id: '35',
    name: 'Comedy'
  },
  {
    id: '80',
    name: 'Crime'
  },
  {
    id: '99',
    name: 'Documentary'
  },
  {
    id: '18',
    name: 'Drama'
  },
  {
    id: '10751',
    name: 'Family'
  },
  {
    id: '14',
    name: 'Fantasy'
  },
  {
    id: '36',
    name: 'History'
  },
  {
    id: '27',
    name: 'Horror'
  },
  {
    id: '10402',
    name: 'Music'
  },
  {
    id: '9648',
    name: 'Mystery'
  },
  {
    id: '10749',
    name: 'Romance'
  },
  {
    id: '878',
    name: 'Science Fiction'
  },
  {
    id: '10770',
    name: 'TV Movie'
  },
  {
    id: '53',
    name: 'Thriller'
  },
  {
    id: '10752',
    name: 'War'
  },
  {
    id: '37',
    name: 'Western'
  }
]

module.exports = {
  genres
}
```

Then I was able to map over the supplied id's, compare them to the saved data from a local file called `movieGenres.js`. In the MovieCard component I needed a string to display the genres, so the following accomplished the goal: 

```javascript
const MovieCard = ({ id, title, genre_ids, poster_path, average_vote }) => {
  let idStr = id.toString(8)
  let genresStr = ''
  if (genre_ids) {
    genresStr = genre_ids
      .map(id => {
        const item = genreMap.genres.find(item => item.id === id)
        return item ? item.name : null
      })
      .join(', ')
  }
```
In the Movie Detail component, I needed an array to map over to show a listing of genres' using a Bootstrap `Badge`:

```javascript 
let genresArr = []
  if (genre_ids) {
    genresArr = genre_ids.map(gid => {
      const item = genreMap.genres.find(item => item.id === gid)
      genresArr.push(item.name)
      return genresArr
    })
  }

```

Then displaying the Badges:
```jsx
<div>
  <span className="mr-2">Genres:</span>
    {genresArr[0].map(item => (
      <Badge variant="warning" className="mb-1" key={item}>
        {item}
      </Badge>
    ))}
</div>
```