一直在为我目前在编码类的家庭食谱项目工作。这一切都发生在我的create Recipe页面上,问题是我遇到了一个奇怪的事件,状态更新似乎是自己的。我有一个状态变量numOfI
(成分数量),它包含我在页面上创建的组件数组和几个函数,用于从具有状态的数组中添加和删除我创建的组件。这样,用户就可以根据需要添加和删除尽可能多的成分和最终步骤。下面是RecipeNew页面的代码:
import { useEffect, useState } from 'react';
import { createRecipe } from '../services/recipeService';
import IngredientInput from '../componenets/IngredientInput';
export default function RecipeNew(props) {
const [formState, setFormState] = useState({
creator: '',
access: '',
name: '',
ingredients: [{ amount: '', ingred: '' }],
steps: []
});
const [numOfI, setNumOfI] = useState([<IngredientInput first='true' onChange={handleChange}
key={0}/>]);
const [numOfSteps, setNumOfSteps] = useState([]);
console.log(numOfI);
async function handleSubmit(event) {
event.preventDefault();
console.log(formState);
createRecipe(formState);
setFormState({
creator: '',
access: '',
name: '',
ingredients: [{ amount: '', ingred: '' }],
steps: []
});
props.history.push('/home');
}
function handleChange(event) {
console.log(event.target)
setFormState({ ...formState, [event.target.name]: event.target.value });
}
function handleAdditionalIngredient() {
const newArray = [];
newArray.push(
<IngredientInput pos={numOfI.length} key={numOfI.length} handleRemoveIngredient={handleRemoveIngredient}
handleChange={handleChange}
setNumOfI={setNumOfI} numOfI={numOfI} />)
setNumOfI(prevArray => [...prevArray, ...newArray]);
console.log('numOfI');
console.log(numOfI);
}
function handleRemoveIngredient(pos) {
const newArray = [];
console.log('numOfI before removal');
console.log(numOfI)
console.log('Pos Removed')
console.log(pos)
console.log('---------------')
// numOfI.forEach((ing, i) => {
// console.log('Ingred:')
// console.log(ing);
// console.log(' ');
// if(pos === i){
// return;
// } else{
// newArray.push(ing);
// }
// });
console.log('================')
// console.log('New Array')
// console.log(newArray)
// setNumOfI([...newArray])
console.log('Num Of I')
console.log(numOfI)
}
return (
<div>
<form onSubmit={handleSubmit}>
<div className='ingred'>
<input type='text' name='name'
placeholder='Name' onChange={handleChange} />
{numOfI}
<button type="button" onClick={handleAdditionalIngredient}>+</button>
</div>
<div className='steps'>
<textarea cols="40" rows="5" type="" name='steps[]' placeholder={`Step ${numOfSteps + 1}`} />
</div>
<button>Submit</button>
</form>
</div>
);
}
以及我创建的组件的代码(以防万一):
export default function IngredientInput(props){
const amount= `amount[${(props.pos)+1}]`
const ingred= `ingredients[${(props.pos)+1}].ingred`
const checkFirst = props.first === 'true' ? <></> :
<button onClick={() => props.handleRemoveIngredient(props.pos)}
type='button'>-</button>
return(
<div>
<input type='text' name={amount}
onChange={props.handleChange} placeholder='#'/>
<input type='text' name={ingred}
onChange={props.handleChange} placeholder='Ingredient'/>
{checkFirst}
</div>
);
}
使用handleAdditionalIngredient
添加项正确地调整状态,更新发生在函数外部,因为内部的console.log对于状态的异步性质来说太快了,但它确实更新正确。
当我试图使用handleRemoveIngredient
删除一个项目时,问题出现了。随着所有调整numOfI状态的代码被注释掉,在const [state]声明之后的console.log和handleRemoveIngredient
的第一行之间,状态已经完全改变了。下面是浏览器控制台的例子,但发生的另一件事是我按了三次+ (handleAdditionalIngredient
)按钮,然后按了一次剥离的- (handleRemoveIngredient
)按钮。
RecipeNew.js:57 numOfI
RecipeNew.js:58 [{…}] //Inside the handleAdditonalIngredient
RecipeNew.js:22 (2) [{…}, {…}] // In the main RecipeNew function
RecipeNew.js:57 numOfI
RecipeNew.js:58 (2) [{…}, {…}]
RecipeNew.js:22 (3) [{…}, {…}, {…}]
RecipeNew.js:57 numOfI
RecipeNew.js:58 (3) [{…}, {…}, {…}]
RecipeNew.js:22 (4) [{…}, {…}, {…}, {…}]
RecipeNew.js:66 numOfI before removal
RecipeNew.js:67 (2) [{…}, {…}]
正如您可以看到的那样,状态从数组中的4个元素急剧变化为2个元素,而没有任何其他因素影响状态,调用nummofi的唯一行是console.log()的行。
我做错了什么?或者我不知道什么会导致这种情况发生?过去两天我一直在谷歌上搜索,没有任何结果,所以如果有任何建议或帮助,我将不胜感激。
第一个明显的问题是,你将反应节点存储在状态变量
const [numOfI, setNumOfI] = useState([<IngredientInput first='true' onChange={handleChange}
key={0}/>]);
而在下面你试图存储不同的类型
setNumOfI([...newArray])
表面上是一个数字。
我将首先查看这个状态变量的类型,您可能正在尝试存储一个数字,然后通过循环迭代呈现。
你应该考虑重新考虑你的配料数据结构,也许给它一个id
字段,并且只存储你的状态中的配料数据。