【问题标题】:Update nested array in this.setState更新 this.setState 中的嵌套数组
【发布时间】:2019-02-25 03:22:56
【问题描述】:

我昨天问了这个问题,但在阅读时我发现我的措辞很糟糕,请允许我重新措辞。我想要实现的是拥有一个初始组(一个数组)并允许用户创建更多组(添加数组)。他们可以在每个组中上传图片。对于每张上传的图片,我想在其受尊敬的组中显示预览。

上图是初始组(一个空数组)。你可以从我目前的状态看出这一点。

this.state = {
    data: {
        groups: [[]]
    },
    preview: [[]]
}

我通过组映射以显示上面的图像,其中包含一个输入 [“file”] 以及右侧显示照片预览的 div。这段代码看起来是这样的..

groups.map((element, index) => {
    return <div className="form-group" key={index}>
        <label htmlFor={"photos-" + index} className="form-group-label">Upload Photo</label>
        <input
            id={"photos-" + index}
            type="file"
            style={{display: 'none'}}
            onChange={(e, index) => this.handlePhotoChange(e, index)}
        />
        <div className="form-group-previews">
            {
                preview[index].map((image, id) => {
                    return <img key={id} src={image} alt={id} />
                })
            }
        </div>
    </div>
})

我遇到的问题是将文件和图像预览放入相关数组(组和预览)中的相同索引中。现在我的 onChange 事件处理程序看起来像这样。

handlePhotoChange(e, index) {
    e.preventDefault()

    let reader = new FileReader()
    let file = e.target.files[0]

    const { data, preview } = this.state
    const { groups } = data

    reader.onloadend = () => {
        this.setState({
            data: {
                ...data,
                groups: [...groups, [...index, file]] // error
            },
            preview: [...preview, [...index, reader.result]] // error
        })
    }

    reader.readAsDataURL(file)
}

我试图用 this.setState 中的扩展运算符做的事情是不可能的吗?我想要实现的似乎更像是

groups[index]: [...groups[index], file]
preview[index]: [...preview[index], reader.result]

但类似的东西是语法错误。有没有更好的方法来做到这一点?

解决方案**

【问题讨论】:

  • 我会选择不同的数据结构并尝试使用查找对象
  • Ryne 问题解决了吗?我已经添加了我的答案你尝试过吗?

标签: reactjs


【解决方案1】:

您必须根据索引从数组中抓取项目,然后将file 添加到刚刚抓取的项目中。

index 只是一个数字,您正在对它应用扩展运算符,这是错误的原因。

reader.onloadend = () => {
  // clone the array from state so that it is not mutated directly
  let clonedGroups = [...groups];
  let clonedPreview = [...preview];
  // grab the corresponding item based on the index
  let groupItem = clonedGroups[index] || [];
  let previewItem = clonedPreview[index] || [];

  // Update the corresponding item
  groupItem = [...groupItem, file];
  previewItem = [...previewItem, reader.result];

  // set the state with updated array objects
  this.setState({
    data: {
      ...data,
      groups: clonedGroups
    },
    preview: clonedPreview
  })
}

【讨论】:

  • 你不认为这样数组只是被浅拷贝
  • 这就是状态必须是不可变的意图。直接改变状态是个坏主意。
  • 文件上传后我控制台日志,组为空,预览未定义。这段代码是有道理的,虽然我要玩弄它,因为我现在不明白为什么文件和 reader.result 会显示为 null 或 undefined
  • 这个答案中的代码与我的解决方案有点不同,但这让我明白了。我用解决方案编辑了我的问题
【解决方案2】:

尝试以这种方式更新状态:

 reader.onloadend = () => {
    this.setState({
        data: {
            ...data,
            groups: groups.map((groupItem, i)=> i===index?[...groupItem,...file] : groupItem )
        },
        preview:  preview.map((previewItem, i)=> i===index?[...previewItem,...reader.result] : previewItem )
    })
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-03
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    相关资源
    最近更新 更多