useState 变量不是删除函数中的最新版本,React
我有一个包含问题字段的 div 列表。每次单击按钮,我都会添加一行新的问题字段,并在状态中记住整个列表以及有多少行。我尝试添加一个删除按钮,但当我的删除函数时,似乎会记住状态变量中的值,从创建行时开始。我该如何解决这个问题,以便我可以在 HandleDelete 函数中访问完整列表?
const OefeningAanvragenDagboek = () => {
const { t, i18n } = useTranslation()
const [questionCount, setQuestionCount] = useState(1)
const [questionList, setQuestionList] = useState([])
const createNewLine = () =>{
var newLine=
<div>
<Field type="text" name={"vraag" + questionCount}/>
<Field component="select" name={"antwoordMogelijkheid"+questionCount}>
<option value="">...</option>
<option value="open">{t('oefeningAanvragenDagboek.open')}</option>
<option value="schaal">{t('oefeningAanvragenDagboek.scale')}</option>
</Field>
<Field type="text" name={"type"+questionCount}/>
<button onClick={() => HandleDelete(questionCount-1)}>{t('assignmentCard.delete')}</button>
</div>
setQuestionList(questionList => [...questionList, newLine])
setQuestionCount(questionCount+1)
}
const HandleDelete = (index)=> {
console.log(questionList)
// setQuestionList(questionList.splice(index, 1))
}
return (
<div>
<button onClick={createNewLine}>{t('oefeningAanvragenDagboek.addQuestion')}</button>
{questionList}
</div>
)
}
使用
功能性
setState
,因为
HandleDelete
在
questionList
上有闭包
setQuestionList(questionList => questionList.splice(index, 1))
Both state and props received by the updater function are guaranteed to be up-to-date.
您可以将事件处理程序从容器传递给子组件,然后从客户端 调用 事件处理程序。
例如,假设我有一个显示项目列表的应用程序,每个项目都有一个删除按钮,用于将其从列表中删除。在这种情况下,父组件将向子组件提供 项目列表 和 事件处理程序 ,然后子组件将负责 渲染 和 调用事件处理程序 。
查看此 codesandbox ,我从中粘贴了以下代码:
import React, { useState } from "react";
import "./styles.css";
export function List(props) {
return (
<div>
{props.items.map((i, idx) => (
<div class="item" key={idx}>
{i} <span onClick={() => props.onDelete(idx)}>X</span>
</div>
))}
</div>
);
}
export default function App() {
const [items, setItems] = useState([
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
"Item 6"
]);
const deleteItem = (index) => {
if (index >= 0 && index < items.length) {
const newItems = items.slice();
newItems.splice(index, 1);
setItems(newItems);
}
};
return (
<div className="App">
<List items={items} onDelete={deleteItem}></List>
</div>
);
}
主要解决 OP 评论部分的问题 ,在撰写本文时,除了问题之外还获得了赏金。
存在问题的 SandBox: https://codesandbox.io/s/charming-architecture-9kp71?file=/src/App.js
基本上,解决这个问题的方法是针对回调函数的参数执行所有操作。就我上面链接的沙盒问题而言,如果您查看下面代码中的
removeToast
,则操作是在
list
数组上完成的。
有问题的代码:
export default function App() {
const [list, setList] = useState([]);
const removeToast = (id) => {
const newList = list.filter(({ toastId }) => toastId !== id);
setList([...newList]);
};
const addToast = () => {
const toastId = Math.random().toString(36).substr(2, 9);
const newList = [
...list,
{
toastId,
content: (
<>
<button onClick={() => removeToast(toastId)}>Hi there</button>
Hello {toastId}
</>
)
}
];
setList([...newList]);
};
return (
<>
<button onClick={addToast}>Show Toast</button>
<Toaster removeToast={removeToast} toastList={list} />
</>
);
}
但是由于
removeToast
在
list
上有一个闭包,我们需要对先前的状态进行过滤,而该状态再次可以通过 setState 回调的第一个参数访问
修复:
const removeToast = (id) => {
setList((prev) => {
return prev.filter(({ toastId }) => toastId !== id);
});
};
解决方案: https://codesandbox.io/s/suspicious-silence-r1n41?file=/src/App.js