DEV Community

Cover image for My Cook Book
Joseph Martin
Joseph Martin

Posted on

My Cook Book

For my phase 2 project with Flatiron school I decided to make a cook book to store some of my favorite recipes, and some new ones that I would like to try. This web application was written with React, and this is my first React project. I had a lot of fun working on this project. The major features of this project are the list of recipes that can be filtered in to category's,
list of recipes
and a form to add new recipes to the database.
new recipe form
On the list of recipes you can click on one to see the full recipe.
full recipe
One piece of code that was both challenging, and a lot of fun to work on was the filter. First I had to create a dropdown to select a category.

<div id="category-filter">
  <label htmlFor="category">Filter By: </label>
  <select name="category">
    <option value="all">Choose a Category...</option>
    <option value="appetizers">Appetizers</option>
    <option value="beverages">Beverages</option>
    <option value="breakfast">Breakfast</option>
    <option value="desserts">Desserts</option>
    <option value="main dishes">Main Dishes</option>
    <option value="salads">Salads</option>
    <option value="side dishes">Side Dishes</option>
    <option value="soups and stews">Soups and Stews</option>
  </select>
</div>
Enter fullscreen mode Exit fullscreen mode

After That I had to control the form in state so I could access the value later.

// the recipes prop is a list of recipes from an api
function RecipePage({ recipes }) {

  {/* here I set the initial state */}
  const [filterBy, setFilterBy] = useState("all")

  <div>
    <label htmlFor="category">Filter By: </label>

    {/* now I can set the value and onChange */}
    <select
      name="category"
      value={filterBy}
      onChange={e => setFilterBy(e.target.value)}
    >
      {/* ...
      options
      ... */}
    </select>
    {/* pass recipes and filterBy in to RecipeList */}
    <RecipeList recipes={recipes} filterBy={filterBy} />
  </div>
}
Enter fullscreen mode Exit fullscreen mode

Now that I have the value of the dropdown stored in state as filterby, I can pass that value in to RecipeList. In RecipeList we receive two props, recipes, the list of recipes, and filterBy, the selected category on the dropdown. For recipes, I don't want to alter it (I'll need the original list later) so I create a new variable in state, filteredRecipes. Next, I filter through the list of recipes and find all of the recipes that match the currently selected category. Then, I save those recipes to filteredRecipes so I can re-render the list with just the selected recipes.

function RecipeList({ recipes, filterBy }) {
  // set new state variable
  const [filteredRecipes, setFilteredRecipes] = useState([])

  //This is a side effect that runs everytime filterBy changes
  useEffect(() => {
    if (filterBy === "all") {
      setFilteredRecipes(recipes)
    } else {

      // first, I create a new array
      let newFilteredRecipes = []

      // next I filter through the list
      recipes.filter(recipe => {

        // if the category's match, 
        if (recipe.category === filterBy) {

          // add the recipe to the array
          newFilteredRecipes.push(recipe)
        }
      })
      // set the new filtered list to filteredRecipes
      setFilteredRecipes(newFilteredRecipes)
    }
  }, [filterBy])

  // now the JSX has filtered recipes to work with
  return (
    <div>
      {filteredRecipes.length !== 0 &&
        filteredRecipes.map(recipe => (
          <RecipeListing key={recipe.id} recipe={recipe} />
        ))
      }
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

In conclusion, I created a dropdown, and I controlled the dropdown in state. Then, I compared each recipes category to the value in state. Lastly, I stored the new list of filtered recipes in it's own state variable as to not alter the original list and to re-render the filtered list.

Top comments (1)

Collapse
 
joe1350 profile image
Joseph Martin

Thank you. I really appreciate that.