DEV Community

Cover image for MyFamilyRecipe React/Redux app using Rails API
Chaya Deaver
Chaya Deaver

Posted on • Updated on

MyFamilyRecipe React/Redux app using Rails API

I can't believe it's finally here. I was reflecting today that this time last year, I had started learning to code a little bit of JavaScript on Grasshopper App and today I am submitting my final project at Flatiron School. Let's jump in.

I came about this idea when talking with my husband. He tells me that I need to get his grandmother's recipe for one particular chicken dish that he likes from his mom. I had said that I'll just copy it from her notebook the next time I see her. I was hesitant about asking my mother-in-law for recipes through a text message because she would send me pictures of these recipes that were very hard to read. I would rather just copy it down myself. It dawned me that I could make an application that keeps track of family recipes and the idea grew from there.

It started out as a simple application where a user can submit recipes. My potential for this will be to create a social media type platform where users can share family recipes and users can scroll through a list of recipes and comment on them. I didn't quite get around to implementing commenting on recipes for this project but I would like to add this feature in the future. I ran into a few roadblocks so I'd like to highlight three of them. The three roadblocks I want to highlight are the following:

  1. Rendering the correct links in my navigation bar when a user is logged in.
  2. Understanding Redux store and implementing asynchronous fetch using Redux Thunk.
  3. Managing changes in a nested form.

The last roadblock was a particularly tough one and it made me feel really accomplished when I found the solution. I will touch on these roadblocks and elaborate on what I did to achieve the solution.

Roadblock #1: NavBar

I wanted to build a navigation bar so I built it using react-bootstrap. I also wanted it to be dynamic where it would render different links when a user signed in. I used a conditional to render different results and stored it inside an arrow function called renderNavbar.

NavBar.jsx
Alt Text

I then pass in the state of current user from my Redux store on line 60 and set it to a boolean value using !!. When a user is logged in, they should be able to view the recipes they've added, add a new recipe, and edit their own recipes. It also shows a logout link when a user is logged in and when they log out, it will show a sign up and log in link.

Alt Text

Roadblock #2: Understanding Redux and Thunk

In order to fix the first roadblock, I had to understand the second roadblock first. The example I will use for this will be the currentUser reducer. The currentUser is a reducer in the Redux store. I utilized Redux Thunk to make fetch requests to my Rails API to get the current user stored there. First, I have a file called store.jsx that stores of my reducers and combine them together with combineReducer like so...

store.jsx
Alt Text

I made an asynchronous action creator inside my middleware folder called actions and make a fetch request to a custom action inside my SessionsController in my Rails API.

actions/currentUser.jsx
Alt Text

Custom route in routes.rb
Alt Text

Custom action in sessions_controller.rb
Alt Text

logged_in? on line 16 is defined in application_controller

application_controller.rb
Alt Text

In addition to using currentUser state from Redux store in NavBar.jsx, I also used it in my RecipeCard component to render a link to edit a recipe only if a userId is equal to currentUserId`. This authorizes a user to edit only a recipe that belongs to them.

RecipeCard.jsx
Alt Text

Roadblock #3: Managing Nested Forms

This application has three forms total: 1) signup form, 2) login form, 3) recipe form. Both signup and login form state are managed by Redux. I originally was going to use Redux to manage recipe form as well. The problem I ran into with recipe form was that it was a nested form. The three main models in the backend have these relationships:

  • User has many recipes
  • Recipe has many ingredients and belongs to user
  • Ingredient belongs to recipe

I was running into a problem handling changes in the ingredient field form. It wouldn't show the changes in the correct attributes in Redux store. Because a recipe has many ingredients, I also wanted there to be a button that will continually render ingredient fields as I needed to add more ingredients to the recipe. One of the things that fixed it was adding this line of code in recipe.rb in API.

recipe.rb
Alt Text

I had completely forgot about accepts_nested_attributes_! I also needed to add this to strong params in RecipeController.

recipe_controller.rb
Alt Text
I added an attribute called ingredients_attributes as an array with attributes from ingredients table. By doing this, the RecipeController is in charge of creating ingredients in the form. Previously, I had both controller in charge of their own CRUD actions. One of the ways I tried to work around this was creating a separate recipe form component and an ingredient form component and importing ingredient form component into recipe form. Now that recipe is responsible for creating ingredients, there was no need for two separate form components. I made a new recipe form that handled form state locally but still submits form data to Redux store where recipe data is stored. Inside the local state in RecipeForm, I assigned ingredients as an array of objects.

RecipeForm.jsx
Alt Text

By assigning ingredients to an array, I was able to map through it and each time the button "add a new ingredient" is clicked, a new ingredient is added to the array.

RecipeForm.jsx
Alt Text

The Add a new ingredient takes in onClick addIngredient. The addIngredient handles adding a new ingredient instance to the previous state of ingredients.

Alt Text

The recipe form renders with one ingredient field with a button to allow a user to add as many ingredients as they would like.

I am glad that I was able to get through these roadblocks. I have so many more plans for this application and I will continue to work on this project. I do plan on deploying this application on Heroku once I have decide how I want the RecipeCard component to look. It has been an insane ten months and I have come a long way. I came into Flatiron School not knowing how to code and now I am able to build a full-scale web application. I am excited to learn more and continue on this journey!

react-project-demo

Frontend repo
Backend repo

Top comments (0)