Javascript 为什么在react应用程序中仅更改映射函数中的最后一项?

Javascript 为什么在react应用程序中仅更改映射函数中的最后一项?,javascript,reactjs,Javascript,Reactjs,我有一个呈现文件列表的组件。其上的方法是简单的添加、更新和删除。我正在经历的行为,尖叫关闭问题,但我不知道是什么。该组件将处于状态的文件列表存储为数组。所以在渲染时,我只是在它们上面映射。更新项的工作方式与您预期的一样,因此我相信正在为该方法传递正确的id,但是删除总是传递映射到的最后一个项的id 因此,如果我添加了3项: 1.文件#1 2.文件#2 3.文件#3 我点击更新#2-所有按预期工作文件#2被设置为我放在那里的任何文件,状态反映了正确的列表 但如果我试图删除文件1或2,则会删除文件3

我有一个呈现文件列表的组件。其上的方法是简单的添加、更新和删除。我正在经历的行为,尖叫关闭问题,但我不知道是什么。该组件将处于状态的文件列表存储为数组。所以在渲染时,我只是在它们上面映射。更新项的工作方式与您预期的一样,因此我相信正在为该方法传递正确的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的
属性。这可能不是问题的根源,但也可能是。当数组数据支持的元素列表发生更改时,该键有助于跟踪哪些元素需要重新渲染。谢谢,我知道性能需要键,但我没有意识到忽略它们可能会导致这种明显的错误