0

I'm creating a simple recipe app that uses edamam's API. The data returned from edamam doesn't have a unique ID for each recipe element. As a result, I'm trying to use UUID to create unique Ids for all recipes that are returned. However, neither of the solutions that I'm applying creates a unique id.

My Recipe Component

import React, {useState, useEffect} from 'react';
import Recipe_Tiles from './Recipe_Tiles'
import { API_ID, API_KEY} from '../../Config'
import uuid from 'uuid/v4'



import '../../App.css'


function Recipe() {

  //Initialized states
  const [Search, setSearch] = useState("");
  const [Term, setTerm] = useState();
  const [Recipe, setRecipe] = useState([]);

  let id = uuid();



//useEffect will run again if the Term state is updated
  useEffect(() => {
      getAPI();
  }, [Term]);

//method to retrieve recipes
  const getAPI = () => {
    fetch(`https://api.edamam.com/search?q=${Term}&app_id=${API_ID}&app_key=${API_KEY}`)
    .then(response => response.json())
    .then(response => {
      console.log(response)
      setRecipe(response.hits)
    })
  }

  const handleChange = (e) => {
    setSearch(e.target.value);
  }

 const handleSubmit = (e) => {
   e.preventDefault();
   setTerm(Search);
   setSearch("");
 }

  return (
    <div 
    className="App"
    style = {{marginLeft: "15px"}}
    >

        <h1 style = {{textAlign: 'center'}}>The Recipe App</h1>

      <form  onSubmit = {handleSubmit}>
      <div className="row inputs">
        <div className="input-field col s6">
        <label htmlFor="first_name"> Search for Recipes</label>
          <input 
          className = "recipe-input"
          type = "text"
          value = {Search}
          onChange = {handleChange}
          />
        </div>
        <button 
            className="btn waves-effect waves-light button-input" 
            type="submit"
            onSubmit = {handleSubmit} 
            name="action">Search
              <i className="material-icons right">local_dining</i>
          </button>
    </div>
    </form>

   {/* 
   The recipe tiles component is used to create the recipe cards.
   Once data is retrieved from the API, it'll be passed as props to the component. 
   */}
    {Recipe.map(i => (
      <Recipe_Tiles 
      title = {i.recipe.label} 
      calories = {i.recipe.calories}
      image = {i.recipe.image}
      URL = {i.recipe.url}
      ingredients = {i.recipe.ingredients}
      id = {id}
       />
    ))}

    </div>
  );
}

export default Recipe;

My Recipe_Tiles Component:

import React from 'react'

export default function Recipe_Tiles ({title, calories, image, URL,ingredients, id}) {

    return(
        <div class="card">

        <div class="card-image waves-effect waves-block waves-light">
          <img class="activator" src={image} alt = "this is a recipe"/>
        </div>
        <div class="card-content">

          <span class="card-title activator grey-text text-darken-4" 
          style = {{fontSize: '15px',lineHeight:'20px', fontWeight: '700'}}>{title}
                <i class="material-icons right">more_vert</i>
          </span>
          <br />
          <hr style = {{width: '40%', marginLeft: '90px', marginBottom: '10px'}}/>
            <p> Calories: {Math.floor(calories)} | Ingredients: {ingredients.length}</p>
          <br />
          <p><a href={URL}>View The Complete Recipe Here</a></p>
        </div>

        <div class="card-reveal">
          <span 
          class="card-title grey-text text-darken-4"
          style = {{fontSize: '15px', lineHeight:'20px', fontWeight: '700', marginRight: '20px',marginTop: '50px'}}>
              Ingredients List:<i class="material-icons right">close</i></span>
              <ol>
                  {ingredients.map(i => (
                      <li style = {{marginLeft: '-40px'}}>{i.text}</li>
                  ))}
              </ol>
           <p>My id is {id}</p>
        </div>
      </div>

    )
}

Solution attempt 1:

In my Recipe component,create a variable called id and set it to UUID(). Next, pass this variable as a props in my map function. The problem with this solution is that it creates a UUID that is the same for all recipes.

Solution attempt 2

In my Recipe component and in my map function, create a prop called Id and pass it this: i.uuid(). However, I receive a Unhandled Rejection (TypeError): i.uuid is not a function error.

Here is the data returned from Edamam's API:

q: "chicken",
from: 0,
to: 10,
more: true,
count: 168106,
hits: [
{
recipe: {
uri: "http://www.edamam.com/ontologies/edamam.owl#recipe_b79327d05b8e5b838ad6cfd9576b30b6",
label: "Chicken Vesuvio",
image: "https://www.edamam.com/web-img/e42/e42f9119813e890af34c259785ae1cfb.jpg",
source: "Serious Eats",
url: "http://www.seriouseats.com/recipes/2011/12/chicken-vesuvio-recipe.html",
shareAs: "http://www.edamam.com/recipe/chicken-vesuvio-b79327d05b8e5b838ad6cfd9576b30b6/chicken",
yield: 4,
dietLabels: [],
healthLabels: [],
cautions: [],
ingredientLines: [],
ingredients: [],
calories: 4055.7632762010808,
totalWeight: 2765.5901364771207,
totalTime: 60,
totalNutrients: {},
totalDaily: {},
digest: []
},
bookmarked: false,
bought: false
},
{
recipe: {
uri: "http://www.edamam.com/ontologies/edamam.owl#recipe_8275bb28647abcedef0baaf2dcf34f8b",
label: "Chicken Paprikash",
image: "https://www.edamam.com/web-img/e12/e12b8c5581226d7639168f41d126f2ff.jpg",
source: "No Recipes",
url: "http://norecipes.com/recipe/chicken-paprikash/",
shareAs: "http://www.edamam.com/recipe/chicken-paprikash-8275bb28647abcedef0baaf2dcf34f8b/chicken",
yield: 4,
dietLabels: [],
healthLabels: [],
cautions: [],
ingredientLines: [],
ingredients: [],
calories: 3033.2012500008163,
totalWeight: 1824.6125000003276,
totalTime: 0,
totalNutrients: {},
totalDaily: {},
digest: []
},
bookmarked: false,
bought: false
},

Any suggestions or feedback would be much appreciated!

Linda Paiste
  • 38,446
  • 6
  • 64
  • 102
traveler316
  • 97
  • 3
  • 11

2 Answers2

1

I was also faced to this issue concerning how to get the recipe ID. Finally, I found a solution, maybe this will help you.

First of all, each recipe has an unique 'uri' from Edamam API. Inside the uri, you will be able to find the recipe-ID (after the '#recipe_).

So, you could try to extract the ID from the uri string by using a small function like that :

extractIdFromUri(uri) {
    return uri.split('#recipe_').pop()
}

It's worked for me.

jbb
  • 56
  • 4
0

Update the hits array using map() to return a new array with the uniqueId as an additional key. This can be achieved using ES6 spread syntax

const updatedHits = response.hits.map((recipe) => {
    uniqueId: uuid(),
    ...recipe
});

setRecipe(updatedHits);

Josh
  • 827
  • 5
  • 7
  • Hi, thanks for the comment. However, I'm not following. Am I creating this function within my getAPI method? If so, it fails to compile due to this error: `Expected an assignment or function call and instead saw an expression` – traveler316 Apr 26 '20 at 19:23
  • No. You call this function after getting a response from the getApi method. You use the response to generate a new hits Array where all elements have a unique id. – Josh Apr 26 '20 at 19:24
  • So, this is how I'm doing it: https://codeshare.io/5QR14Q If I'm understanding correctly, I'm still getting errors. Sorry for the added explanations - still learning react! – traveler316 Apr 26 '20 at 19:38
  • I've modified the code here https://codeshare.io/5QR14Q check it out and see if its working now – Josh Apr 26 '20 at 20:02
  • Unfortunately, there's some parsing issues with this part: `Recipe: { ...hit.recipe, id: uuid() }` – traveler316 Apr 26 '20 at 20:15