我有一个包含对象数组的对象
var timer : Timer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
timer = Timer()
}
@IBAction func startAction(_ sender: Any) {
timer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: false, block: { (make) in
print("ack did")
})
}
@IBAction func cancelAction(_ sender: Any) {
timer?.invalidate()
}
我使用此对象数组控制表中Textfield的状态
initialPreconfigTodoState = {
todos: [
{
title: 'title1',
dueDate: new Date(),
create: true,
assignedTo: 'role',
},
{
title: 'title2',
dueDate: new Date(),
create: true,
assignedTo: 'role',
}]
};
当我尝试在Textfield中键入内容时,我不知道会发生什么,但是我需要为每个键入的字符单击Textfield,我认为是useState挂钩,在重新呈现组件时会导致此问题,我找不到解决方案。
这是我在onChange回调上的句柄函数,
const [preconfig, setPreconfig] = useState(initialPreconfigTodoState);
{preconfig.todos.map((todo, index) => {
return (
<TableRow
className="h-64 cursor-pointer"
key={Math.random()}
>
<TableCell className="th" component="th" scope="row">
<TextField
id={`titleForm${index}`}
name={`titleForm${index}`}
onChange={(event) => handleTitle(event, index)}
value={todo.title}
type="text"
variant="outlined"
required={todo.create ? true : false}
fullWidth
/>
</TableCell>
};
这是完整的代码
const handleTitle = (event, index) => {
let newArray = [...preconfig.todos];
newArray[index] = {
...newArray[index],
title: event.target.value,
};
setPreconfig({ todos: newArray });
答案 0 :(得分:1)
那是因为TableRow上的key={Math.random()}
。
将其更改为key={index}
,它应该可以工作。
使用Math.random()
,您的键会更改每个渲染,并且react会丢失其引用。
答案 1 :(得分:0)
问题实际上是由当时useState
引起的。您的整个表单(我想它是某种形式)都会更改在render
中从其映射的数组。难怪整个表格都会重新呈现。
显而易见的解决方案是仅在提交时存储输入值(例如,处于状态)并更新原始数组(通过setPreconfig
)。