I have a working function when I pass an array of data inside the same component.
This function makes an array of all possible combinations of ingredients, then makes API calls to find all possible drinks, and then filters through to find the ones that only contain the ingredients in the array.
However, when I try to pass the array of data as props from another component, the function stops working half way through...
The props are received fine and the function starts but then it stops working on line 64-72. The valid results are not getting pushed to my result array.
The two images show function passed with props and hard coded array:
Any help would be appreciated!!
Component code:
import React from 'react'
import { useEffect, useState } from 'react'
import axios from 'axios';
import './style.css'
function MultiSearch({clickState}) {
//console.log(ingredients)
console.log(clickState)
const [filtResult, setFiltResult] = useState([])
const ingredients = ['Vodka', 'Orange juice']
//console.log(ingredients)
// use usestate to add salt and other ingredients like that as default. Then add user ingredients onto existing array
function getCombinations(valuesArray) {
let combi = [];
let temp = [];
let slent = Math.pow(2, valuesArray.length);
for (let i = 0; i < slent; i ) {
temp = [];
for (let j = 0; j < valuesArray.length; j ) {
if ((i & Math.pow(2, j))) {
temp.push(valuesArray[j]);
}
}
if (temp.length > 0) {
combi.push(temp);
}
}
combi.sort((a, b) => a.length - b.length);
// console.log(combi.join("\n"));
console.log(combi.filter(x => x.length > 1))
combi = combi.filter(x => x.length > 1)
// Fetch data with combinations array
let drinkList = []
let clen = combi.length
const fetchAll = async (combi) => {
for (let i = 0; i < clen; i ) {
let possible = await axios.get(`https://www.thecocktaildb.com/api/json/v2/9973533/filter.php?i=${combi[i].join(',')}`)
let data = possible.data.drinks
typeof(data) !== 'string' && drinkList.push(data)
}
//flatten array of arrays into one.
const concatList = drinkList.flat(1)
let fullList = []
let conLen = concatList.length
//lookup each drink into new array with full details
for (let i = 0; i < conLen; i ) {
let res = await axios.get(`https://www.thecocktaildb.com/api/json/v2/9973533/lookup.php?i=${concatList[i].idDrink}`)
let data = res.data.drinks
fullList.push(data)
}
//Flatten array of arrays into single array
fullList = fullList.flat(1)
console.log(fullList)
fullList.length > 0 && ingredients.push('Salt', 'Olive', 'Tea', 'Sugar')
let result = []
let valid = true;
*** // Code starts to fail below ***
fullList.map(drink => {
for (let i = 1; i <= 15; i ) {
console.log(drink[`strIngredient${i}`])
if (drink[`strIngredient${i}`] !== null && ingredients.indexOf(drink[`strIngredient${i}`]) === -1) {
valid = false;
break;
} else if (ingredients.indexOf(drink[`strIngredient${i}`]) !== -1){
valid = true;
}
}
valid === true && result.push(drink)
*** // End code fail ***
})
console.log(result)
// Filter result to remove duplicates
const ids = result.map(x => x.idDrink)
const filtered = result.filter(({idDrink}, index) => !ids.includes(idDrink, index 1))
setFiltResult(filtered)
}
fetchAll(combi)
}
useEffect(() => {
getCombinations(ingredients);
}, [clickState])
console.log(filtResult)
return (
filtResult.length !== 0 ? filtResult.map(drink => {
console.log(drink)
const {strDrink, strDrinkThumb} = drink
return (
<>
<h2>{strDrink}</h2>
<img className="multi-search" src={strDrinkThumb} alt={strDrink} />
</>
)
})
:
<h2>No search rn</h2>
)
}
export default MultiSearch
CodePudding user response:
It seems like you are mutating the ingredients
props in the part where you 'Flatten array of arrays into single array'. When ingredients
is a local variable, it works fine but when you pass ingredients
from props, it doesn't work in the expected way. I think copying that prop to a local array might help.
Props mutation
fullList.length > 0 && ingredients.push('Salt', 'Olive', 'Tea', 'Sugar')
Copying array in function scope
function getCombinations(valuesArray) {
let originalIngredients = [...valuesArray];
}
Hope this works.
CodePudding user response:
the fix:
for (let i = 1; i <= 15; i ) {
if (drink[`strIngredient${i}`] !== null && !newIngredients.includes(drink[`strIngredient${i}`].toLowerCase().replace(/\s/g, ''))) {
valid = false;
break;
} else {
valid = true
}