为什么在react应用程序中只更改地图功能中的最后一项?

IT技术 javascript reactjs
2021-05-15 14:26:41

我有一个呈现文件列表的组件。它的方法是简单的添加、更新和删除。我遇到了尖叫关闭问题的行为,但我不知道是什么。该组件将 state 中的文件列表存储为数组。所以在渲染时我只是映射它们。更新项目的工作正如您所期望的那样,所以我相信正在为该方法传递正确的 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>
  )
};
3个回答

当您不使用键或使用键作为索引时,这种意外行为很常见。

只需使用slide.idas key 即可解决您的问题

 {
          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 识别哪些项目已更改、添加或删除。应该为数组内的元素提供键,以赋予元素一个稳定的身份:

因此,如果您将 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>
  )

就我而言,我已经给出了所有的键因为我使用的是 Slick Slider 组件。所有组件都相互渲染(一个在另一个下面)。对于活动 Slider增加 z-index 和 position: relative解决了上述问题。

.slick-active {
            .see-more{
                z-index: 10;
                position: relative;
            }
        }