React Hooks 表单处理:使用多个字符串项和一个数组项更新对象的状态
Posted
技术标签:
【中文标题】React Hooks 表单处理:使用多个字符串项和一个数组项更新对象的状态【英文标题】:React Hooks Form Handling: Update the state of an object with multiple string items and one array item 【发布时间】:2020-07-10 22:48:51 【问题描述】:我正在学习使用钩子制作应用程序的 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>
);
我正在努力寻找解决方案。
我们将不胜感激。
【问题讨论】:
这一行没有触发你的测试变量已经被声明的错误?setTest(test => ( ingredients: [...test.ingredients, query] ));
也许用这个例子解释一下你想达到什么目的是件好事?
【参考方案1】:
我看的方式,你需要在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
有查询->状态改变->但是addItem的查询不能改变
【讨论】:
他的问题不在于 memoization,因为重新调用函数相当于有一个没有依赖的 usecallback【参考方案2】:您提供的代码需要一些格式(又名: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。
【讨论】:
【参考方案3】:问题在于这一行:setTest(test => ( ingredients: [...test.ingredients, query] )
在使用 react 类组件时,如果不像 this.setState( ingredients: [...test.ingredients, query] )
那样传播整个先前的状态,就可以设置状态,因为在内部 react 已经将您传递到 this.setState
的新对象与先前的状态合并。
在反应钩子中,React.useState
不会进行合并,因此您必须合并之前的状态,例如 setState(test => ( ...test, ingredients: [...test.ingredients, query] )
。
edit:您还在组件顶部声明了变量test
。我建议将setTest
中的test
参数重命名为其他名称。
【讨论】:
您在回答之前检查过我的回答吗? ?♂️以上是关于React Hooks 表单处理:使用多个字符串项和一个数组项更新对象的状态的主要内容,如果未能解决你的问题,请参考以下文章
React Hooks 在设置状态的同时处理多个动作的方式是啥?
React Hooks:使用useState更新状态不会立即更新状态[重复]