Javascript 正在删除中的列表项,请保留旧项
我想从列表中删除所选项目 当我单击delete(删除)时,右项将从列表内容中删除,但在UI上,我始终会触发列表项 我似乎跟踪JSXJavascript 正在删除中的列表项,请保留旧项,javascript,reactjs,Javascript,Reactjs,我想从列表中删除所选项目 当我单击delete(删除)时,右项将从列表内容中删除,但在UI上,我始终会触发列表项 我似乎跟踪JSX键并显示最后的值 这里有一个 const Holidays=(道具)=>{ 控制台日志(道具); const[state,setState]=useState({…props}); useffect(()=>{ 设置状态(道具); console.log(状态); }, []); const addNewHoliday=()=>{ const obj={开始:“12/
键
并显示最后的值
这里有一个
const Holidays=(道具)=>{
控制台日志(道具);
const[state,setState]=useState({…props});
useffect(()=>{
设置状态(道具);
console.log(状态);
}, []);
const addNewHoliday=()=>{
const obj={开始:“12/12”,结束:“12/13”};
setState(更新(状态,{daysoflist:{$push:[obj]}});
};
常数deleteHoliday=(i)=>{
const objects=state.daysOffList.filter((elm,index)=>index!=i);
log({objects});
setState(更新(状态,{daysoflist:{$set:objects}}));
console.log(state.daysOffList);
};
返回(
问题
您正在使用数组索引作为React键,并且正在变异基础数据数组。当您单击第二个条目将其删除时,第三个元素向前移动以填补空白,现在为刚刚删除的元素分配了React键。React使用该键帮助协调,如果该键保持稳定,React在重新提交UI时退出
您也不能在列队状态更新后立即控制台日志状态,并期望看到更新的状态
setState(update(state, { daysOffList: { $set: objects } }));
console.log(state.daysOffList);
React状态更新是异步的,在渲染周期之间进行处理。上述更新可以并且将只记录当前渲染周期中的状态值,而不是排队等待下一个渲染周期的更新
解决方案
为每个开始/结束数据对象使用GUID。这是一个非常好的包,具有很好的唯一性保证,并且使用起来非常简单
import { v4 as uuidV4 } from 'uuid';
// generate unique id
uuidV4();
要具体解决代码中的问题,请执行以下操作:
- 将
id
属性添加到数据中
const daysOffList = [
{ id: uuidV4(), start: "12/12", end: "12/15" },
{ id: uuidV4(), start: "12/12", end: "12/17" },
{ id: uuidV4(), start: "12/12", end: "12/19" }
];
...
const addNewHoliday = () => {
const obj = {
id: uuidV4(),
start: "12/12",
end: "12/13",
};
setState(update(state, { daysOffList: { $push: [obj] } }));
};
- 更新处理程序以使用要删除的id
const deleteHoliday = (id) => {
const objects = state.daysOffList.filter((elm) => elm.id !== id);
setState(update(state, { daysOffList: { $set: objects } }));
};
- 使用element id属性作为React键
{state.daysOffList?.map((elm, i) => {
return (
<Flex key={elm.id} gap="gap.small">
...
</Flex>
);
})}
演示
注意:如果您不想(或不能)安装额外的第三方依赖项,那么您可以使用自己的id生成器。这将在紧要关头起作用,但您确实应该寻求真正经验证的解决方案
const genId = ((seed = 0) => () => seed++)();
genId(); // 0
genId(); // 1
问题是你正在使用数组中的索引作为键。这是。你对旧项目说什么,你的意思是你不需要jsx来再次渲染?我不明白,你能解释更多细节吗?plz:)为了确认@PatrickRoberts说的话,如果你改成key={JSON.stringify(elm)}
您会发现正确的项目被删除。但是,对于“密钥”来说,这并不是一个好的长期解决方案我的意思是,如果我有A,B,C,我删除B,是我的数据,它会得到A,C,但在UI中它会显示A,B,如果我再次删除A,在UI中它会显示A,B,C,因为你使用数组索引作为React键,并改变底层数据,索引0和1仍然存在,并且没有改变,所以React bails会重新提交与之关联的JSX这些键。选择映射数据固有/唯一的react键。如果数据不具有此质量,请使用GUID属性扩充数据以用于此目的。
{state.daysOffList?.map((elm, i) => {
return (
<Flex key={elm.id} gap="gap.small">
...
</Flex>
);
})}
<Button
primary
icon={<TrashCanIcon />}
text
onClick={() => deleteHoliday(elm.id)}
/>
useEffect(() => {
console.log(state.daysOffList);
}, [state.daysOffList]);
const genId = ((seed = 0) => () => seed++)();
genId(); // 0
genId(); // 1