I am still new to React and have been doing small projects lately to get better. I am currently working on a nutrition webpage that sets calorie goals and obtains foods from an API. This project consists of 2 components FoodItem and Main.
The Main component calculates calories and displays the search results from the API. Here lies the problem. When the search bar first receives a name, it displays nothing. However, it displays the intended search results after a backspace (deleting one letter from the word). This is seen in the screenshots.
Full word:
After deleting one letter:
Here is the function responsible for displaying the Search Results:
updateResult(name) {
console.log(name);
if (name == "") {
this.setState({
foodResult: []
})
return;
}
let result = [];
let url = 'https://api.edamam.com/api/food-database/parser?app_id=e056fc58&app_key=key&ingr=' + name;
fetch(url)
.then(
function(response) {
return response.json();
}
).then(function(jsonData) {
for (let i = 0; i < jsonData.hints.length; i++) {
foods.push({
name: jsonData.hints[i].food.label,
calories: Math.round(jsonData.hints[i].food.nutrients.ENERC_KCAL)
})
}
})
console.log(foods);
foods = removeDuplicates(foods);
for (let i = 0; i < foods.length; i++) {
if (foods[i].name.toUpperCase().includes(name.toUpperCase())) {
result.push(
<FoodItem name ={foods[i].name} calories ={foods[i].calories} updateFoods = {this.displayEatenFoods} isEaten = {false} checkItem = {this.checkItem}/>)
}
}
console.log(result);
this.setState({
foodResult: result
});
}
Full code:
import React from "react";
import ReactDOM from "react-dom";
//////////////////
let foods = [];
function removeDuplicates(arr) {
var unique = [];
for (let i = 0; i < arr.length; i++) {
let current = arr[i].name;
let add = true;
for (let i = 0; i < unique.length; i++) {
if (current == unique[i].name) add = false;
}
if (add) unique.push(arr[i]);
}
return unique;
}
///////////////////
class FoodItem extends React.Component {
constructor(props) {
super(props);
this.state = { addDone: false, disable: false };
this.addEaten = this.addEaten.bind(this);
}
addEaten() {
if (this.props.updateFoods(this.props.name))
this.setState({ addDone: false, disable: true });
else this.setState({ addDone: true });
}
render() {
if (this.props.isEaten) {
return (
<div>
{this.props.name}
  Calories :{this.props.calories}
</div>
);
}
if (!this.state.addDone) {
return (
<div>
{this.props.name}
  Calories :{this.props.calories}
 
<button primary onClick={this.addEaten} disabled={this.state.disable}>
Eat
</button>
</div>
);
}
return null;
}
}
class Main extends React.Component {
constructor(props) {
super(props);
this.state = {
goal: " ",
remaining: " ",
goalEntered: false,
foodSearch: "",
foodResult: [],
EatensFoods: [],
allowance: " ",
calories: ""
};
this.setGoal = this.setGoal.bind(this);
this.changeGoal = this.changeGoal.bind(this);
this.changeFoodSearch = this.changeFoodSearch.bind(this);
this.displayEatenFoods = this.displayEatenFoods.bind(this);
this.checkItem = this.checkItem.bind(this);
this.changeCalorieSearch = this.changeCalorieSearch.bind(this);
}
changeGoal(event) {
this.setState({ goal: event.target.value });
}
setGoal(event) {
this.setState({ goalEntered: true, remaining: this.state.goal });
event.preventDefault();
}
changeFoodSearch(event) {
this.setState({ foodSearch: event.target.value });
this.updateResult(event.target.value);
}
changeCalorieSearch(event) {
this.setState({ calories: event.target.value });
}
updateResult(name) {
console.log(name);
if (name == "") {
this.setState({ foodResult: [] });
return;
}
let result = [];
let url =
"https://api.edamam.com/api/food-database/parser?app_id=e056fc58&app_key=key&ingr=" +
name;
fetch(url)
.then(function(response) {
return response.json();
})
.then(function(jsonData) {
for (let i = 0; i < jsonData.hints.length; i++) {
foods.push({
name: jsonData.hints[i].food.label,
calories: Math.round(jsonData.hints[i].food.nutrients.ENERC_KCAL)
});
}
});
console.log(foods);
foods = removeDuplicates(foods);
for (let i = 0; i < foods.length; i++) {
if (foods[i].name.toUpperCase().includes(name.toUpperCase())) {
result.push(
<FoodItem
name={foods[i].name}
calories={foods[i].calories}
updateFoods={this.displayEatenFoods}
isEaten={false}
checkItem={this.checkItem}
/>
);
}
}
console.log(result);
this.setState({ foodResult: result });
}
displayEatenFoods(name) {
let tempEaten = [];
let disableFlag = false;
for (let i = 0; i < foods.length; i++) {
if (foods[i].name.toUpperCase() == name.toUpperCase()) {
if (this.checkItem(foods[i].calories, foods[i].name)) {
tempEaten.push(
<FoodItem
name={foods[i].name}
calories={foods[i].calories}
updateFoods={this.displayEatenFoods}
isEaten={true}
checkItem={this.checkItem}
/>
);
} else {
disableFlag = true;
}
}
}
tempEaten = removeDuplicates(tempEaten);
tempEaten = this.state.EatensFoods.concat(tempEaten);
this.setState({ EatensFoods: tempEaten });
return disableFlag;
}
checkItem(cal, name) {
let newRemainder = this.state.remaining - cal;
if (newRemainder < 0) {
this.setState({ allowance: "You can't eat " + name });
return false;
}
this.setState({
remaining: newRemainder,
allowance: "You can eat " + name
});
return true;
}
render() {
if (!this.state.goalEntered) {
return (
<center>
<form onSubmit={this.setGoal}>
<label>
Please Enter your desired calories
<input
type="text"
value={this.state.goal}
onChange={this.changeGoal}
/>
</label>
<input type="submit" value="OK" />
</form>
</center>
);
}
return (
<div>
<center>
<h1>Maximum Calories:{this.state.goal}</h1>
<h2>Remaining Calories:{this.state.remaining}</h2>
<h3>{this.state.allowance}</h3>
<form>
<label>
Search foods
<input
type="text"
placeholder="Enter Name"
value={this.state.foodSearch}
ref={a => {
this.searchValue = a;
}}
onChange={this.changeFoodSearch}
/>
<input
type="text"
placeholder="Calories,Min+,Max,Min-Max"
value={this.state.calories}
onChange={this.changeCalorieSearch}
/>
</label>
</form>
{this.state.foodResult}
<h2>Eaten Foods:</h2>
{this.state.EatensFoods}
</center>
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById("root"));