React Project: The Sports Report
My fifth and final project for Flatiron School is a single-page application called The Sports Report. It is a web application that finds new articles for you about your favorite sports players and teams, all in one place. This project is meant to be a culmination of all the things I have learned over the past 5 months.
The project requirements were fairly open-ended. We had to use the create-react-app generator and have a Rails API backend. We needed to have some stateless components and make use of client-side routing. Additionally, we needed to make use of async actions and redux-thunk middleware to send and receive data.
How My App Works
- The web page loads up, bringing you to a landing page with some information and options to log in or sign up
- The Rails backend will create new users and check their information is valid
- When logging in, the backend will authenticate the user
- After logging in or signing up, the user is routed to a home page where they have 2 options to choose between players or teams
- After choosing either option, the user will be routed to the player or team page where they can see a list of the favorites. The page here uses a master-detail pattern
- When a favorite is clicked on the left-hand side, the right-hand side loads up the articles related to the favorite
- This involves using async requests and redux-thunk middleware so the component doesn’t break waiting for the articles’ contents to be fetched
- Once the articles are loaded, a user can read the full article by clicking the link and it will open a new tab and take them to the article.
- If a user no longer considers the player or team a favorite, they can delete them from the list.
- If the user wants to switch to teams or players, they can use the menu button to route them to the appropriate page.
- Finally, the user can log out and it will take them back to the landing page.
Challenges I Worked Through
One interesting part of my project is how I set up my backend and how it interacts with the frontend. Given how many players and teams exist, I used TheSportsDB API to get their information. However, the API does not have an endpoint of all the players or all the teams in the database. The only way to find a player or team is to use their search endpoint. Thus, I could not seed my database all the players or teams. Plus, a player can change teams and their information will update, so seeding would be disadvantageous. After thinking through how to handle this, I decided to set up a Player table and Team Table with 2 Joins tables to create a has_many to has_many relationship between players/teams and users.
So on the front-end, when a user searched for a player or team, it would hit the SportsDB API, and return the search results. When the user selects from the results, this will send a POST request to my Rails API Backend. The backend would then check to see if that player/team existed in my database; If it did, then it simply establishes an association between the user and the player. If the player or team did not exist, then it would create a new row for them in the database. Additionally, I was able to solve the issue of a player or team’s information updating because I could just run the update method after a player was created or found and provide it the new information from the API. By setting it up this way, my database did not have to be seeded initially with any player or team information nor did I have to make a gigantic fetch request from the API (which wasn’t possibly anyways with the endpoints available). The database would be user-driven and fill up as users added players and teams.
Another big part of the project was using Redux-Thunk middleware to handle async requests. What I am going to talk about does require some prior knowledge of Redux, Store, Actions, and Dispatch.
For example, with my web app, when you click on a player/team name, the app is going to render a component with all the articles. However, it can’t display any articles until they arrive from the data source (an API). If I try to, it will break and show me an error. By using Redux Thunk, in my store that holds my state object, I set up a boolean key:value pair called “requesting” (set to false). Then anytime a team or player was clicked, it would invoke an action function. This action function does 2 things:
- It makes the fetch request to the news API I was using to get the articles.
- Second, it sends its first dispatch to update my store’s state by changing “requesting” to true.
My component that displays the articles is constantly aware of the status of “requesting”. Using a ternary operator, I had it display 2 different things based on “requesting” being true or false. Thus, my app doesn’t break and I can tell the user “Hey, I’m working on getting the information you request, just hold on for a couple of seconds.”
Back in my action, the fetch request I initiated will eventually complete. Then using the “.then” functions that follow a fetch request, I can send my second dispatch action, which will update the store to hold all the articles and turn “requesting” back to false. Since “requesting” is false, the component will look for the articles, which are now present in the store, and it can display them without breaking.
Setting that up was a lot of fun and showed me I had a good understanding of the flow of the code of my project. Incorporating it also makes for a much better User Interface experience.
For the styling and design of the project, I used Material UI. A small quirk I ran into when incorporating Material UI was that they used all functional components and hooks to provide styling. I had initially set up my project with class components. Hooks do not work with class components, so I had to convert any component that was using Material UI. Eventually, I just changed all the components to functional for uniformness. The only issue there was making sure all of my syntax was adjusted because functional components differ syntactically in how they handle props and state. As it is, React is turning more towards using functional components, so it was good practice to do both.
I had a lot of fun building out this application. If you want to use it for yourself, you can check out the deployed version at https://the-sports-report.herokuapp.com/. If you want to see my code, see the repo here.
It is amazing to realize I have come to the end of my time at Flatiron School. I have learned so much in 5 months and I can’t wait to start applying my skills in the real world.
The Journey Continues!