Javascript Promise.all中的setState钩子仅更新组件状态的最后一个元素
下面是程序和代码 我的组件的状态是一个TODO数组,通过Javascript Promise.all中的setState钩子仅更新组件状态的最后一个元素,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,下面是程序和代码 我的组件的状态是一个TODO数组,通过useStatehook创建和更新。每个todo都可以通过自己的“保存”按钮进行编辑和保存,该按钮调用saveTodoasync函数 我正在尝试实现一个Save All按钮,该按钮将为承诺中的每个todo调用saveTodo函数。All-请参阅下面的handleOnSaveAllClicked 现在只更新最后一个todo。有什么线索可以全部更新吗 多谢各位 async function stall(stallTime = 3000) {
useState
hook创建和更新。每个todo都可以通过自己的“保存”按钮进行编辑和保存,该按钮调用saveTodo
async函数
我正在尝试实现一个Save All按钮,该按钮将为承诺中的每个todo调用saveTodo函数。All
-请参阅下面的handleOnSaveAllClicked
现在只更新最后一个todo。有什么线索可以全部更新吗
多谢各位
async function stall(stallTime = 3000) {
await new Promise(resolve => setTimeout(resolve, stallTime));
}
const Todo = ({ todo, onFormChanged }) => {
const onChange = (key) => {
return (e) => onFormChanged(todo.id, { [key]: e.target.value });
};
return (
<div>
<label>
<p>Name</p>
</label>
<input type="text" value={todo.name} onChange={onChange("name")} />
</div>
);
};
const App = () => {
const initDate = new Date()
const initialTodos = [
{ id: 1, name: "Todo 1", time: initDate},
{ id: 2, name: "Todo 2", time: initDate }
];
const [todos, setTodos] = React.useState(initialTodos);
const saveTodo = async (todo) => {
//simulate async http call
await stall(1000)
const newTodo = { ...todo, ...{ time: new Date() } };
setTodos(todos.map((t) => (t.id === newTodo.id ? newTodo : t)));
};
const handleOnSaveAllClicked = async () => {
await Promise.all(todos.map(t => saveTodo(t)))
}
const handleOnSaveClicked = async (id) => {
const todo = todos.find((t) => t.id === id);
await saveTodo(todo)
};
const handleFormChange = (id, data) => {
const todo = todos.find((t) => t.id === id);
const newTodo = { ...todo, ...data };
setTodos(todos.map((t) => (t.id === id ? newTodo : t)));
};
return (
<div>
<button type="button" onClick={(e) => {
e.preventDefault();
handleOnSaveAllClicked();
}}
>Save All</button>
{todos.map((t) => {
return (
<div>
<form onSubmit={(e) => e.preventDefault()}>
<p>{t.name} lasted saved on {t.time.toLocaleString()}</p>
<button
type="button"
onClick={(e) => {
e.preventDefault();
handleOnSaveClicked(t.id);
}}
>
Save
</button>
<Todo todo={t} key={t.id} onFormChanged={handleFormChange} />
</form>
</div>
);
})}
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
异步函数暂停(暂停时间=3000){
等待新的承诺(resolve=>setTimeout(resolve,stallTime));
}
常量Todo=({Todo,onFormChanged})=>{
const onChange=(键)=>{
return(e)=>onFormChanged(todo.id,{[key]:e.target.value});
};
返回(
名字
);
};
常量应用=()=>{
const initDate=新日期()
常量initialTodos=[
{id:1,名称:“Todo 1”,时间:initDate},
{id:2,名称:“Todo 2”,时间:initDate}
];
const[todos,setTodos]=React.useState(initialTodos);
const saveTodo=async(todo)=>{
//模拟异步http调用
等待摊位(1000)
const newTodo={…todo,{time:new Date()};
setTodos(todos.map((t)=>(t.id==newTodo.id?newTodo:t));
};
const handleOnSaveAllClicked=async()=>{
等待Promise.all(todos.map(t=>saveTodo(t)))
}
const handleon saveclicked=async(id)=>{
const todo=todos.find((t)=>t.id==id);
等待保存todo(todo)
};
常量handleFormChange=(id,数据)=>{
const todo=todos.find((t)=>t.id==id);
常数newTodo={…todo,…data};
setTodos(todos.map((t)=>(t.id==id?newTodo:t));
};
返回(
{
e、 预防默认值();
handleOnSaveAllClicked();
}}
>拯救一切
{todos.map((t)=>{
返回(
e、 preventDefault()}>
{t.name}持续保存在{t.time.toLocaleString()上
{
e、 预防默认值();
handleon(t.id);
}}
>
拯救
);
})}
);
};
render(,document.getElementById(“根”));
问题在于您使用的是创建函数时存在的
TODO
,而不是最新的TODO
。因此,您最终会覆盖在此期间所做的任何更改。要使用最新版本,请使用setTodos的函数版本:
setTodos(prev => prev.map((t) => (t.id === newTodo.id ? newTodo : t)));
您正在通过闭包捕获TODO,因此saveTodo(即使是最后一个)在更新之前获得对
TODO
的引用。有趣的是,我从未见过此函数版本。为什么这不是默认值?它将防止所有陈旧的国家问题?非常感谢。