React Hooks 表单处理:使用多个字符串项和一个数组项更新对象的状态
React Hooks Form Handling: Update the state of an object with multiple string items and one array item
我正在学习使用钩子制作应用程序的 React。我一直在关注教程,但我想对其进行一些更改。我有一个包含多个字符串项和一个数组项的对象:
const [recipe, setRecipe] = useState({
title: '',
description: '',
ingredients: [],
instructions: '',
tags: 'none'
});
教程最初包含所有字符串项,因此以下代码可以完美地更新状态:
setRecipe({ ...recipe, [e.target.name]: e.target.value });
}
所有相似的输入字段之一的示例。
<input
type='text'
placeholder='Title'
name='title'
value={title}
onChange={onChange}
/>
现在我已将其中一项更改为数组,它不再有效。我尝试了几种方法,例如:
const [test, setTest] = useState({
ingredients: ['bread', 'milk', 'honey']
});
const [query, setQuery] = useState('');
const updateQuery = e => {
setQuery(e.target.value);
};
const addItem = e => {
e.preventDefault();
setTest(test => ({ ingredients: [...test.ingredients, query] }));
};
return (
<div>
<button className='btn btn-light btn-block' onClick={addItem}>
Add ingredient
</button>
<input
type='text'
placeholder='Description'
name='ingredients'
value={ingredients}
onChange=(updateQuery)
/>
</div>
<div>
{test.ingredients.map(data => (
<ul key={data}>{data}</ul>
))}
</div>
);
我正在努力寻找解决方案。
不胜感激。
在我看来,您需要在 addItem 中使用 useCallback,如 updateQuery
const updateQuery = useCallback(e => {
setQuery(e.target.value);
},[]);
const addItem = useCallback(e => {
e.preventDefault();
setTest(test => ({ ingredients: [...test.ingredients, query] }));
},[query]);
就是hooks原理,想了解这个原理的可以搜索Principle of useCallback
。
如果你想知道简单的方法,我可以告诉你一件事。
在渲染组件时,addItem
有query -> state change -> 但是addItem的query不能改变
您提供的代码需要一些格式(又名:onChange={onChange}
而不是 onChange
并且您的输入值需要 query
而不是成分)
此外,您在编辑时并没有恢复旧状态。
我向你的状态添加了一个非数组整数字段
const [test, setTest] = React.useState({
nonArray: 0,
ingredients: ["bread", "milk", "honey"]
});
然后我将您的 addItem 更改为:
const addItem = e => {
e.preventDefault();
setTest(old => ({ ...old, ingredients: [...old.ingredients, query] }));
setQuery("");
};
它似乎很有魅力。
请检查此 working codesandbox,其中基本上包含您的代码。
这一行有问题:setTest(test => ({ ingredients: [...test.ingredients, query] })
当使用 react class 组件时,设置状态而不像 this.setState({ ingredients: [...test.ingredients, query] })
那样传播整个先前的状态会很好,因为内部 react 已经合并了您传递给 [=12] 的新对象=] 与以前的状态。
在 React 钩子中,React.useState
不进行合并,因此您必须像 setState(test => ({ ...test, ingredients: [...test.ingredients, query] })
.
那样合并之前的状态
编辑:您还在组件的顶部声明了变量 test
。我建议将 setTest
中的 test
参数重命名为其他名称。
我正在学习使用钩子制作应用程序的 React。我一直在关注教程,但我想对其进行一些更改。我有一个包含多个字符串项和一个数组项的对象:
const [recipe, setRecipe] = useState({
title: '',
description: '',
ingredients: [],
instructions: '',
tags: 'none'
});
教程最初包含所有字符串项,因此以下代码可以完美地更新状态:
setRecipe({ ...recipe, [e.target.name]: e.target.value });
}
所有相似的输入字段之一的示例。
<input
type='text'
placeholder='Title'
name='title'
value={title}
onChange={onChange}
/>
现在我已将其中一项更改为数组,它不再有效。我尝试了几种方法,例如:
const [test, setTest] = useState({
ingredients: ['bread', 'milk', 'honey']
});
const [query, setQuery] = useState('');
const updateQuery = e => {
setQuery(e.target.value);
};
const addItem = e => {
e.preventDefault();
setTest(test => ({ ingredients: [...test.ingredients, query] }));
};
return (
<div>
<button className='btn btn-light btn-block' onClick={addItem}>
Add ingredient
</button>
<input
type='text'
placeholder='Description'
name='ingredients'
value={ingredients}
onChange=(updateQuery)
/>
</div>
<div>
{test.ingredients.map(data => (
<ul key={data}>{data}</ul>
))}
</div>
);
我正在努力寻找解决方案。
不胜感激。
在我看来,您需要在 addItem 中使用 useCallback,如 updateQuery
const updateQuery = useCallback(e => {
setQuery(e.target.value);
},[]);
const addItem = useCallback(e => {
e.preventDefault();
setTest(test => ({ ingredients: [...test.ingredients, query] }));
},[query]);
就是hooks原理,想了解这个原理的可以搜索Principle of useCallback
。
如果你想知道简单的方法,我可以告诉你一件事。
在渲染组件时,addItem
有query -> state change -> 但是addItem的query不能改变
您提供的代码需要一些格式(又名:onChange={onChange}
而不是 onChange
并且您的输入值需要 query
而不是成分)
此外,您在编辑时并没有恢复旧状态。
我向你的状态添加了一个非数组整数字段
const [test, setTest] = React.useState({
nonArray: 0,
ingredients: ["bread", "milk", "honey"]
});
然后我将您的 addItem 更改为:
const addItem = e => {
e.preventDefault();
setTest(old => ({ ...old, ingredients: [...old.ingredients, query] }));
setQuery("");
};
它似乎很有魅力。
请检查此 working codesandbox,其中基本上包含您的代码。
这一行有问题:setTest(test => ({ ingredients: [...test.ingredients, query] })
当使用 react class 组件时,设置状态而不像 this.setState({ ingredients: [...test.ingredients, query] })
那样传播整个先前的状态会很好,因为内部 react 已经合并了您传递给 [=12] 的新对象=] 与以前的状态。
在 React 钩子中,React.useState
不进行合并,因此您必须像 setState(test => ({ ...test, ingredients: [...test.ingredients, query] })
.
编辑:您还在组件的顶部声明了变量 test
。我建议将 setTest
中的 test
参数重命名为其他名称。