Javascript 为什么在react应用程序中仅更改映射函数中的最后一项?
我有一个呈现文件列表的组件。其上的方法是简单的添加、更新和删除。我正在经历的行为,尖叫关闭问题,但我不知道是什么。该组件将处于状态的文件列表存储为数组。所以在渲染时,我只是在它们上面映射。更新项的工作方式与您预期的一样,因此我相信正在为该方法传递正确的id,但是删除总是传递映射到的最后一个项的id 因此,如果我添加了3项: 1.文件#1 2.文件#2 3.文件#3 我点击更新#2-所有按预期工作文件#2被设置为我放在那里的任何文件,状态反映了正确的列表 但如果我试图删除文件1或2,则会删除文件3 我错过了什么Javascript 为什么在react应用程序中仅更改映射函数中的最后一项?,javascript,reactjs,Javascript,Reactjs,我有一个呈现文件列表的组件。其上的方法是简单的添加、更新和删除。我正在经历的行为,尖叫关闭问题,但我不知道是什么。该组件将处于状态的文件列表存储为数组。所以在渲染时,我只是在它们上面映射。更新项的工作方式与您预期的一样,因此我相信正在为该方法传递正确的id,但是删除总是传递映射到的最后一个项的id 因此,如果我添加了3项: 1.文件#1 2.文件#2 3.文件#3 我点击更新#2-所有按预期工作文件#2被设置为我放在那里的任何文件,状态反映了正确的列表 但如果我试图删除文件1或2,则会删除文件3
// npm modules
import React, { useState } from 'react';
import randomstring from 'randomstring';
// components
import { PrimaryButton, InlineButton } from "../buttons/buttons";
import { AdminInput } from "../inputs/textInputs";
export const AdminSlides = ({ setSlides }) => {
const [ state, updateState ] = useState({
slides: [],
});
function setState(value){
updateState( prevState => ({
...prevState,
...value
}));
}
function addSlide(){
const slides = state.slides;
const id = randomstring.generate({ length: 5, charset: 'alphabetic' })
slides.push({ id, slide: null });
setState({ slides });
// send current state to parent component
if (setSlides) setSlides(state.slides);
}
function removeSlide(id){
const slides = state.slides.filter(item => item.id !== id);
setState({ slides });
}
function setSlide(file, id){
const slides = state.slides.map(item => {
if (item.id === id) item.slide = file;
return item;
});
setState({ slides });
// send current state to parent component
if (setSlides) setSlides(state.slides);
}
return (
<div>
{
state.slides.map(slide => (
<div className='m-b:1'>
<AdminInput
type='file'
onChange={e => setSlide(e.target.files[0], slide.id)}
className='m-b:.5'
/>
<InlineButton className='m:0' onClick={()=>removeSlide(slide.id)}>Remove</InlineButton>
</div>
))
}
<PrimaryButton onClick={addSlide}>Add Slide</PrimaryButton>
</div>
)
};
//npm模块
从“React”导入React,{useState};
从“randomstring”导入randomstring;
//组成部分
从“./按钮/按钮”导入{PrimaryButton,InlineButton};
从“./inputs/textInputs”导入{AdminInput};
导出常量AdminSlides=({setSlides})=>{
const[state,updateState]=useState({
幻灯片:[],
});
函数设置状态(值){
updateState(prevState=>({
…国家,
价值
}));
}
函数addSlide(){
常量幻灯片=state.slides;
const id=randomstring.generate({length:5,字符集:'字母'})
slides.push({id,slide:null});
设置状态({slides});
//将当前状态发送到父组件
if(设置滑块)设置滑块(状态滑块);
}
函数removeSlide(id){
const slides=state.slides.filter(item=>item.id!==id);
设置状态({slides});
}
函数setSlide(文件,id){
常量幻灯片=state.slides.map(项=>{
如果(item.id==id)item.slide=文件;
退货项目;
});
设置状态({slides});
//将当前状态发送到父组件
if(设置滑块)设置滑块(状态滑块);
}
返回(
{
state.slides.map(slide=>(
setSlide(e.target.files[0],slide.id)}
className='m-b:.5'
/>
removeSlide(slide.id)}>Remove
))
}
添加幻灯片
)
};
当您不使用键或将键用作索引时,这种意外行为很常见
只要使用slide.id
作为键,您的问题就会得到解决
{
state.slides.map(slide => (
<div className='m-b:1' key={slide.id}>
<AdminInput
type='file'
onChange={e => setSlide(e.target.files[0], slide.id)}
className='m-b:.5'
/>
<InlineButton className='m:0' onClick={()=>removeSlide(slide.id)}>Remove</InlineButton>
</div>
))
}
{
state.slides.map(slide=>(
setSlide(e.target.files[0],slide.id)}
className='m-b:.5'
/>
removeSlide(slide.id)}>Remove
))
}
如前所述
键有助于识别哪些项已更改、已添加或已删除。应为数组中的元素提供键,以使元素具有稳定的标识:
所以,若您将key属性添加到map函数中的div元素,那个么您的问题就会得到解决
return (
<div>
{
state.slides.map((slide, index) => (
<div key={slide.id} className='m-b:1'>
<input
type='file'
onChange={e => setSlide(e.target.files[0], slide.id)}
className='m-b:.5'
/>
<button className='m:0' onClick={()=>removeSlide(slide.id)}>Remove</button>
</div>
))
}
<button onClick={addSlide}>Add Slide</button>
</div>
)
返回(
{
state.slides.map((幻灯片,索引)=>(
setSlide(e.target.files[0],slide.id)}
className='m-b:.5'
/>
removeSlide(slide.id)}>Remove
))
}
添加幻灯片
)
在我的例子中,我已经给出了所有的键。因为我使用的是光滑的滑块组件。所有组件都彼此渲染(一个低于另一个)。对于活动滑块,增加z索引和位置:相对修复了上述问题
.slick处于活动状态{
.看更多{
z指数:10;
位置:相对位置;
}
}
每张幻灯片都应该有一个具有唯一ID的键
属性。这可能不是问题的根源,但也可能是。当数组数据支持的元素列表发生更改时,该键有助于跟踪哪些元素需要重新渲染。谢谢,我知道性能需要键,但我没有意识到忽略它们可能会导致这种明显的错误