React 函数在第一次调用时不起作用,但每隔一次就起作用
React function not working on first call, but works every other time
我确定这是一个非常简单的问题,但我尝试了很多不同的方法,但我只会让事情变得更糟。我正在构建一个包含总卡路里的营养应用程序。它应该根据 api 调用的卡路里计算总卡路里,并且在第二次后效果很好。但是第一次显示0
营养成分
const [search, setSearch] = useState("");
const [isLoaded, setIsLoaded] = useState(false);
const [foodId, setFoodId] = useState("");
const [foodList, setFoodList] = useState([]);
const [totalCal, setTotalCal] = useState(0);
const addCal = (cal, totalCal) => {
const total = cal + totalCal;
setTotalCal(total);
};
// Getting user input for an argument to be used later in API call
const getInput = e => {
e.preventDefault();
setSearch(e.target.value);
};
// Submitting user input / starting API call / setting food to be searched
const handleSubmit = e => {
e.preventDefault();
setIsLoaded(true);
// console.log(list);
};
// Function that holds API call using form input
const getNutrition = food => {
const appId = "e124e5bc";
const appKey = "fd3e0319818416b4e8496e3502bcb565";
fetch(
`https://api.nutritionix.com/v1_1/search/${food}?&appId=${appId}&appKey=${appKey}`
)
.then(response => {
return response.json();
})
.then(responseData => {
let foodId = responseData.hits[0].fields.item_id;
fetch(
`https://api.nutritionix.com/v1_1/item?id=${foodId}&appId=${appId}&appKey=${appKey}`
)
.then(response => {
return response.json();
})
.then(responseData => {
setFoodId(foodId);
const foodObject = {
calories: responseData.nf_calories,
protein: responseData.nf_protein,
food: responseData.item_name,
key: foodId,
totalCal: totalCal
};
addCal(foodObject.calories, totalCal);
setFoodList([...foodList, foodObject]);
setIsLoaded(false);
});
});
console.log(isLoaded);
};
// Calling nutrition function that holds API
useEffect(() => {
if (isLoaded) {
getNutrition(search);
setFoodId(foodId);
}
// eslint-disable-next-line
}, [isLoaded]);
return (
<div className={styles.nutritionContainer}>
<FoodForm submit={handleSubmit} input={getInput} />
<table className={styles.center}>
<thead>
<tr>
<th>Food Item</th>
<th>Calories</th>
<th>Protein</th>
<th>Total Calories</th>
<th>Total Protein</th>
</tr>
</thead>
<tbody>
<TableList foodList={foodList} />
</tbody>
</table>
</div>
);
};
export default Nutrition;
包含来自 api 营养成分调用的动态 table 数据的列表
const TableList = ({ foodList }) => {
return foodList.map(item => (
<tr key={item.key}>
<td>{item.food}</td>
<td>{item.calories}</td>
<td>{item.protein}</td>
<td>{item.totalCal}</td>
</tr>
));
};
export default TableList;
因为 isLoaded
最初设置为 false,因此它不会在 useEffect
中调用 getNutrition(search); setFoodId(foodId);
我不能确定为什么你的第一个 api 电话打不通,但当晚我有一些建议可以帮助你。
首先,我根本不会使用 useEffect 挂钩。它不必要地使您的代码复杂化。您只需要在每次提交表单时调用 api 那么为什么不这样做呢?而不是更改 is loaded 值等。这样做之后您可能会发现错误消失了,或者至少会更容易理解代码中发生的事情。
我要做的另一件事是从状态中删除 totalCals。相反,我每次都会计算它,除非你有成千上万的物品,否则它真的不会成为性能问题。这样做的好处是您的代码将更容易理解,如果您说问题是卡路里没有更新,这应该可以解决它。这也意味着您的状态没有非规范化。如果你每次都计算它然后从数组中删除一个项目,你就不用担心忘记也减少总数等
祝你好运!!
我认为您的代码在再次重用相同变量名时存在一些问题,请检查我修复的以下代码。当您使用 isLoaded 值作为默认值时,将搜索值添加到默认值。
希望对您有所帮助。但是现在,你的 api 限制已经结束,因为我测试了很多。 :P
修复 1
useEffect(() => {
if (isLoaded) {
getNutrition(search);
}}, [isLoaded]);
修复 2
const getNutrition (food)=> {
const appId = "e124e5bc";
const appKey = "fd3e0319818416b4e8496e3502bcb565";
fetch(
`https://api.nutritionix.com/v1_1/search/${food}?&appId=${appId}&appKey=${appKey}`
)
.then(response => {
return response.json();
})
.then(responseData => {
let fId = responseData.hits[0].fields.item_id;
setFoodId(fId);
fetch(
`https://api.nutritionix.com/v1_1/item?id=${fId}&appId=${appId}&appKey=${appKey}`
)
.then(response => {
return response.json();
})
.then(responseData => {
console.log("DATA", responseData);
const foodObject = {
calories: responseData.nf_calories,
protein: responseData.nf_protein,
food: responseData.item_name,
key: foodId,
totalCal: totalCal
};
addCal(foodObject.calories);
setFoodList([...foodList, foodObject]);
setIsLoaded(false);
});
});
console.log(isLoaded);};
修复 3
const addCal = cal => {
const total = cal + totalCal;
setTotalCal(total);};
我确定这是一个非常简单的问题,但我尝试了很多不同的方法,但我只会让事情变得更糟。我正在构建一个包含总卡路里的营养应用程序。它应该根据 api 调用的卡路里计算总卡路里,并且在第二次后效果很好。但是第一次显示0
营养成分
const [search, setSearch] = useState("");
const [isLoaded, setIsLoaded] = useState(false);
const [foodId, setFoodId] = useState("");
const [foodList, setFoodList] = useState([]);
const [totalCal, setTotalCal] = useState(0);
const addCal = (cal, totalCal) => {
const total = cal + totalCal;
setTotalCal(total);
};
// Getting user input for an argument to be used later in API call
const getInput = e => {
e.preventDefault();
setSearch(e.target.value);
};
// Submitting user input / starting API call / setting food to be searched
const handleSubmit = e => {
e.preventDefault();
setIsLoaded(true);
// console.log(list);
};
// Function that holds API call using form input
const getNutrition = food => {
const appId = "e124e5bc";
const appKey = "fd3e0319818416b4e8496e3502bcb565";
fetch(
`https://api.nutritionix.com/v1_1/search/${food}?&appId=${appId}&appKey=${appKey}`
)
.then(response => {
return response.json();
})
.then(responseData => {
let foodId = responseData.hits[0].fields.item_id;
fetch(
`https://api.nutritionix.com/v1_1/item?id=${foodId}&appId=${appId}&appKey=${appKey}`
)
.then(response => {
return response.json();
})
.then(responseData => {
setFoodId(foodId);
const foodObject = {
calories: responseData.nf_calories,
protein: responseData.nf_protein,
food: responseData.item_name,
key: foodId,
totalCal: totalCal
};
addCal(foodObject.calories, totalCal);
setFoodList([...foodList, foodObject]);
setIsLoaded(false);
});
});
console.log(isLoaded);
};
// Calling nutrition function that holds API
useEffect(() => {
if (isLoaded) {
getNutrition(search);
setFoodId(foodId);
}
// eslint-disable-next-line
}, [isLoaded]);
return (
<div className={styles.nutritionContainer}>
<FoodForm submit={handleSubmit} input={getInput} />
<table className={styles.center}>
<thead>
<tr>
<th>Food Item</th>
<th>Calories</th>
<th>Protein</th>
<th>Total Calories</th>
<th>Total Protein</th>
</tr>
</thead>
<tbody>
<TableList foodList={foodList} />
</tbody>
</table>
</div>
);
};
export default Nutrition;
包含来自 api 营养成分调用的动态 table 数据的列表
const TableList = ({ foodList }) => {
return foodList.map(item => (
<tr key={item.key}>
<td>{item.food}</td>
<td>{item.calories}</td>
<td>{item.protein}</td>
<td>{item.totalCal}</td>
</tr>
));
};
export default TableList;
因为 isLoaded
最初设置为 false,因此它不会在 useEffect
getNutrition(search); setFoodId(foodId);
我不能确定为什么你的第一个 api 电话打不通,但当晚我有一些建议可以帮助你。
首先,我根本不会使用 useEffect 挂钩。它不必要地使您的代码复杂化。您只需要在每次提交表单时调用 api 那么为什么不这样做呢?而不是更改 is loaded 值等。这样做之后您可能会发现错误消失了,或者至少会更容易理解代码中发生的事情。
我要做的另一件事是从状态中删除 totalCals。相反,我每次都会计算它,除非你有成千上万的物品,否则它真的不会成为性能问题。这样做的好处是您的代码将更容易理解,如果您说问题是卡路里没有更新,这应该可以解决它。这也意味着您的状态没有非规范化。如果你每次都计算它然后从数组中删除一个项目,你就不用担心忘记也减少总数等
祝你好运!!
我认为您的代码在再次重用相同变量名时存在一些问题,请检查我修复的以下代码。当您使用 isLoaded 值作为默认值时,将搜索值添加到默认值。
希望对您有所帮助。但是现在,你的 api 限制已经结束,因为我测试了很多。 :P
修复 1
useEffect(() => {
if (isLoaded) {
getNutrition(search);
}}, [isLoaded]);
修复 2
const getNutrition (food)=> {
const appId = "e124e5bc";
const appKey = "fd3e0319818416b4e8496e3502bcb565";
fetch(
`https://api.nutritionix.com/v1_1/search/${food}?&appId=${appId}&appKey=${appKey}`
)
.then(response => {
return response.json();
})
.then(responseData => {
let fId = responseData.hits[0].fields.item_id;
setFoodId(fId);
fetch(
`https://api.nutritionix.com/v1_1/item?id=${fId}&appId=${appId}&appKey=${appKey}`
)
.then(response => {
return response.json();
})
.then(responseData => {
console.log("DATA", responseData);
const foodObject = {
calories: responseData.nf_calories,
protein: responseData.nf_protein,
food: responseData.item_name,
key: foodId,
totalCal: totalCal
};
addCal(foodObject.calories);
setFoodList([...foodList, foodObject]);
setIsLoaded(false);
});
});
console.log(isLoaded);};
修复 3
const addCal = cal => {
const total = cal + totalCal;
setTotalCal(total);};