简体   繁体   English

如何向文件数组中的对象添加值?

[英]How to add a value to an object inside a array of files?

I am trying to add a key-value pair to an array of files.我正在尝试将键值对添加到文件数组中。 I know that this question is already covered in detail in other articles, eg here .我知道这个问题已经在其他文章中详细介绍过,例如这里 However, the approaches used do not work in my context.但是,所使用的方法在我的上下文中不起作用。 If I missed something or there is another obvious flaw, please apologize!如果我遗漏了什么或有另一个明显的缺陷,请道歉!

I have one or more pictures in an array and would like to add the information to each of these files, whether the picture is a title image or not.我在一个数组中有一张或多张图片,并希望将信息添加到每个文件中,无论图片是否为标题图像。 Ie I want to achieve something like this:即我想实现这样的事情:

  [0:  {File: {name: "Test", 
             lastModified: "125344", 
             etc: "something"}, 
       isTitlePicture: null}
   1:  {File: {name: "Test",
              lastModified: "125344",
              etc: "something"}, 
       isTitlePicture: null}]

With my current code I get the array as as displayed below.使用我当前的代码,我得到如下所示的数组。 This means that the information about the title image is inside the file information.这意味着有关标题图像的信息在文件信息中。 This is what I try to avoid.这是我试图避免的。

  [0: File: {name: "Test", 
             lastModified: "125344", 
             etc: "someting",
             isTitlePicture: {isTitlePicture: null}}
   1:  File: {name: "Test", 
             lastModified: "125344", 
             etc: "someting",
             isTitlePicture: {isTitlePicture: null}]
import React, { Component } from "react";
import { MDBRow, MDBCol, MDBCardBody, MDBCard, MDBCardImage } from "mdbreact";


export class ImageUploadView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      files: [],
      images: []
    };
  }


  onChangeImage(e) {
    const files = Array.from(e.target.files);

    var obj = { isTitlePicture: null };
      
    files.forEach(item => item.isTitlePicture = {...obj}); 

    const images = files.map((file) => URL.createObjectURL(file));
    this.setState({
      files: [...this.state.files, ...files],
      images: [...this.state.images, ...images]
    });
  }

  render() {
    
    return (
      <React.Fragment>
        <div className="card card-body mt-4 mb-4">
          <h1>Add Image</h1>
          <div>
            <input
              type="file"
              onChange={(e) => this.onChangeImage(e)}
              multiple
              //accept=".jpg,.png"
            />
          </div>
          <div className="Images">
            {this.state.images.map((image, i) => (
              <MDBRow
                key={image}
                style={{ margin: "10px", display: "inline-block" }}
              >
                <MDBCol>
                  <MDBCard style={{ width: "5rem" }}>
                    <MDBCardImage
                      className="img-fluid"
                      src={image}
                      waves
                    />
                    <MDBCardBody>       
                    </MDBCardBody>
                  </MDBCard>
                </MDBCol>
              </MDBRow>
            ))}
          </div>
        </div>
      </React.Fragment>
    );
  }
}
  }

Basically I want to have isTitlePicture on the same "level" as File and not within File.基本上我想让 isTitlePicture 与 File 处于同一“级别”,而不是在 File 中。

You can simplify your code a little bit like this:您可以像这样简化代码:

  onChangeImage(e) {
    // Use spread operator like you do everywhere else.
    const files = [...e.target.files].map(file => ({
      isTitlePicture: null,
      file // same as file: file,
    }));
  
    const images = files.map(
      ({file}) => URL.createObjectURL(file)
    );
    
    // When dealing with previous state, the best practice is to pass a
    // function to setState that'll give you access to your mmm... prev state
    // Read below...
    this.setState(prevState => ({
      files: [...prevState.files, ...files],
      images: [...prevState.images, ...images],
    }));
  }

The code above will make your state look like:上面的代码将使您的状态看起来像:

  "files": [
    {
      "isTitlePicture": null,
      "file": {File Object}
    },
    {
      "isTitlePicture": null,
      "file": {File Object}
    }
  ],

  "images": [
    "blob:https://...",
    "blob:https://..."
  ]
}

setState is async, that's why it is better to pass a function when dealing with old state: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous setState是异步的,这就是为什么在处理旧状态时最好传递一个函数: https : //reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

Also, make sure you call URL.revokeObjectURL(file) once you're done with the files.此外,请确保在完成URL.revokeObjectURL(file)调用URL.revokeObjectURL(file) The browser does not release the reference to your files until you manually do it and can cause a memory leak in a single page app.在您手动执行之前,浏览器不会释放对您的文件的引用,这可能会导致单页应用程序中的内存泄漏。

I don't have enough context, but looks like you could include the File URL as part of your files array:我没有足够的上下文,但看起来您可以将文件 URL 作为files数组的一部分:

    const files = [...e.target.files].map(file => ({
      isTitlePicture: null,
      file,
      url: URL.createObjectURL(file),
    }));

Good luck!祝你好运!

Victor胜利者

I think your object structure is wrong.我认为你的对象结构是错误的。

onChangeImage(e) {
    const files = Array.from(e.target.files);

    var result = [];
    files.forEach(item => result.push({file:item,isTitlePicture: null}));

    const images = result.map((file) => URL.createObjectURL(file));
    this.setState({
      files: [...this.state.files, ...result],
      images: [...this.state.images, ...images]
    });
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM