我有一个呈现文件列表的组件。其上的方法是简单的添加,更新和删除。我遇到了尖叫关闭问题的行为,但我不知道是什么。该组件将处于状态的文件列表存储为数组。因此,在渲染时,我只需将它们映射。更新项目的工作原理与您预期的一样,因此我相信该方法将传递正确的ID,但删除操作始终会传递映射到的最后一个项目的ID。
因此,如果我添加了3个项目:1.文件#12.文件#23.文件#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>
)
};
当您不使用键或将键用作索引时,这种意外行为很常见。
只需使用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>
))
}
如https://reactjs.org/docs/lists-and-keys.html所述,
键可帮助React识别哪些项目已更改,添加或删除。应该为数组内的元素赋予键,以赋予元素稳定的身份:
因此,如果您在map函数内部的div元素中添加key属性,您的问题将得到解决。
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>
)