Build a Simple Fullstack App using Rails and React

Learning to code, especially at an accelerated pace, can be stressful. Even more if you’re hoping to turn this new skillset into a career.

Of course, it can also be tremendously gratifying to learn a powerful new skill. Watching a project spring to life from pages of exacting code can be uniquely rewarding. In this same theme, realizing that you’re growing the sort of intuition that will help troubleshoot the inevitable errors encountered along the way, just feels good.

However, most new coders will probably hit a wall at some point where it seems like they’re encountering problems which nobody else seems to have. It can be very draining when it seems like you’re running into a lot of these, and the cumulative effect can make you question whether you’re really cut out for this. Even if you know logically that frustration is part of the journey, and that it will pass, it can still be hard when you’re wading through rivers of inscrutable errors.

I found that it became very comforting to — occasionally — return to a set of tasks which I know I can complete. Connecting a back end database to a front end framework was very much an “aha” moment for me, and building and burning very simple rails/react projects that just added items to a page really helped to boost my confidence. So, I wrote out some instructions for myself, which I’ve basically memorized at this point. I know there are faster and more efficient ways of accomplishing what I’ll demonstrate below, but these steps made sense to me when I was just beginning my adventure. I hope that a few more people will get something out of it, too.

Looking back at my notes, I’m a little embarrassed at how simplistic some of this is. There are certainly faster ways of accomplishing this, but there are also definitely faster ways of accomplishing what I’m working on right now, too. Yet another wonderful aspect of coding is that you can always improve, and I hope to be continually working towards that!

For the project below, I want to use a backend with Ruby on Rails, and create some seeds which I will render using React. You could use anything, but I’m going to pick major league sports and cities. I want to show cities, each of which has a list of major league sports. I’ll limit this to football, baseball, basketball, and hockey.

STEP 1: Create React and Rails apps. I put them both in one directory called sportsball_app, but they could be kept separately, as well.

React App CLI: npx create-react-app sportsball-frontend

Rails App CLI: rails new sportsball_backend — — api . (I like to use the underscore dashes for the frontend and underscores for the backend. This naming convention helps me keep things straight)

STEP 2: Set up a model and resource on the backend.

CLI input: rails g resource Location name:string baseball:string basketball:string football:string hockey:string capital:boolean total_teams:integer

This creates a migration, controller, model, and route, allowing for the creation of the resource :location.

-I want to show one data type other than string, so I’m using capital to mean at least one team uses the capital in their name (e.g., “Denver Nuggets). Rails defaults the variable type to string, so it isn’t necessary to specify “:string”. I’m including it here to be clear exactly what I want. For simplicity, and since I really just want to get items appearing on a page, I decided to not create a separate variable for Team with a belongs_to relationship with the Location variable.

STEP 3: Create some seeds. Below are some seeds I’ve created for this exercise. There is no maximum number. Be sure to include ‘destroy all’ to ensure each object in the collection is frozen. To save space in this blog, checkout the github repo to view seeds: https://github.com/bwesterg/sportsball_backend

STEP 4: Migrate and seed data. This can be done with one CLI command: rails db:{migrate,seed}

Always a good idea to make sure that data was handled correctly, even if there are no errors apparent in the terminal. Simply run: rails c to look at the console, then Location.all to show all the seeds. This ensures that the seeds ‘exist’, so if there are problems in the future getting them to appear on a webpage, we can be certain that the seed data is working.

STEP 5: Make the files show up. This is done by creating an index in the location controller file. Again, to save space, view the controller in the github repo: https://github.com/bwesterg/sportsball_backend

Before considering this ‘done,’ it’s important to start the rails server and ensure the data is rendering correctly. So, in the terminal enter rails s, and open the browser link, http://localhost:3000/. If working correctly, the page will show a graphic which includes the text, “Yay! You’re on Rails.”

To review the seed data, add /locations in the url, so http://localhost:3000/locations . This should show an array of objects, which is the seed data. Note that rails created an id for each object/seed.

STEP 6: Enable CORS (cross origin resource sharing), so these items can appear on the frontend.

- Navigate to the gem file, comment in the line: gem ‘rack-cors’, and save.

- Navigate to the file cors.rb, and comment in the following:

# Rails.application.config.middleware.insert_before 0, Rack::Cors do

allow do

origins ‘example.com’

resource ‘*’,

headers: :any,

methods: [:get, :post, :put, :patch, :delete, :options, :head]

end

end

- Change ‘example.com’ to ‘*’, so any domain can send a request to the application.

- Run the following CLI commang: bundle (stop the rails server first, if you haven’t already).

- Restart the server (rails s), and leave it running.

STEP 7: Open another terminal, and cd into the react app, sportsball-frontend.

STEP 8: Delete boilerplate code and unused icons that are automatically added by npx create-react-app. In App.js, delete ‘import logo from ‘./logo.svg’;’, and everything inside the <div className=“App”> </div>

STEP 9: Change App.js into a class component, because we will need to use state. Change the App function to ‘class App extends Component. Class components must include a render, so add ‘render ()’ above the return. Finally, change the first line to: “import React, { Component } from react;”

STEP 10: Add state, since, at some point — perhaps in another blog — I’ll be changing state and adding/modifying/deleting teams and/or cities.

- state = { locations: [] }

STEP 11: Create a hierarchy of pages for the locations to show up in. Inside the src folder, create a subfolder for components. Inside the components folder, create LocationContainer.js (this will make the locations and their sports teams show up). Also inside the components folder, create LocationItem.js (this is for each individual location and their sports teams).

STEP 12: Set up LocationContainer.js. At this point, I haven’t yet decided if I will use state or not, so I’ll set it up as a functional component.

(to save space in the blog, please view the front end repo here: https://github.com/bwesterg/sportsball-frontend

STEP 13: I’ll use a functional component for LocationItem.js, too, so for now, I can just copy the code from LocationContainer.js. Note, I am changing the <ul> to a <li>, since this is for each location.

STEP 14: Get locations from the backend using the lifecycle method componentDidMount on App.js. This method only runs once, and basically saves bandwidth. There is a great explanation of this here: https://levelup.gitconnected.com/componentdidmakesense-react-lifecycle-explanation-393dcb19e459

- always a good idea to console log the response before doing anything else. Start up the react server by running rpm start, and make sure the backend and front-end are connected. The server will ask if you want to start on port 3001, since the backend is already running on 3000. Just type ‘y’.

componentDidMount(){

fetch(locationsURL)

.then(response => response.json())

.then(console.log)

}

- If things are working correctly, the console should show an array of the seed objects.

STEP 15: Create a getLocations function separate from componentDidMount, and set location. Here, locations is destructured. There are other ways to do this, but in my opinion, this makes the code more readable. So we now have:

componentDidMount(){

this.getLocations()

}

getLocations = () => {

fetch(locationsURL)

.then(response => response.json())

.then(locations => this.setLocation({locations:locations})

//you don’t have to use a key value pair, so the following is equivalent: .then(locations => this.setLocation({locations})

Before moving on, make sure that the data exists in location by going to the components tab in the browser, and viewing App.

STEP 16: Ensure the locations (which are now in location) appear on the page. Add the following to App.js:

- at the top of App.js, import the locationContainer: import locationContainer from ‘./components/locationContainer’;

- under Sportsball app, add <locationContainer />

Currently, only app has location. However, it can be passed to locationContainer by passing as a prop:

- <locationContainer locations={this.state.locations} />

on locationContainer.js, add a function to map todos. I am destructuring props, too:

import React from ‘react’;

import locationItem from ‘./locationItem’

export default function locationContainer({locations}) {

const showlocations = () => {

return locations.map(location => <locationItem key={location.id} {…location} />)

}

//the spread operator gives a prop for each key/value pair in the object

return (

<ul>

location Container

{showLocations()}

//function has to be run

</ul>

)

}

STEP 17: Set up LocationItem.js. Add the following to the file:

import React from ‘react’;

export default function LocationItem({name, baseball, basketball, football, hockey, total_teams, capital}){

//destructuring to indicate items which will be used

return (

<li>

<h2>Location: {name}</h2>

<h4>MLB team(s): {baseball}</h4>

<h4>NBA team(s): {basketball}</h4>

<h4>NFL team(s): {football}</h4>

<h4>NHL team(s): {hockey}</h4>

<h4>Total professional teams: {total_teams}</h4>

<h4>Any teams use state capital in their title? {capital}</h4>

</li>

)

}

At this point, all seeds should be appearing on the page! The formatting is hideous, however.

STEP 18: last step for this blog is to add some styling so the app doesn’t look so terrible. First, add class names to the relevant <li> and <ul>

- add className=“location-item” to the <li> in the LocationItem.js file.

- add className=“location-list” to the <ul> in the LocationContainer.js file

  • in the App.css file, delete the boilerplate code, and add the following:
  • .location-list {

display: flex;

flex-flow: row wrap;

list-style-type: none;

justify-content: space-between;

width: 90%;

}

.location-item {

width: 200px;

height: 500px;

box-shadow: 0 20px 20px -10px lightblue;

border-radius: 6px;

}

In the next blog, I’ll talk about how to do something with the items appearing on the page! Thanks for reading.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store