我有一个包含问题字段的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))
updater函数接收的状态和道具都保证是最新的。
类中的
- setState((
您可以将事件处理程序从容器传递给子级,然后从客户端调用事件处理程序。
例如,假设我有一个显示项目列表的应用程序,每个项目都有一个删除按钮,可以将它们从列表中删除。在这种情况下,父组件将向子组件提供项列表和事件处理程序,然后,子组件将负责渲染并调用事件处理程序。
看看这个代码沙盒,我正在从中粘贴以下代码:
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