简体   繁体   中英

Assign new value to object via spread operator

i have an array of objects acceptedFiles (just one): array of objects

[{
File
path: "jaguar.jpg"
lastModified: 1649928392646
lastModifiedDate: Thu Apr 14 2022 16:26:32 GMT+0700 (GMT+07:00) {}
name: "jaguar.jpg"
size: 7375
type: "image/jpeg"
webkitRelativePath: ""
}]

I need to add new value (preview) to the object everytime user drag and drop image to dropzone. I have a working code with Object.assign. However, i want to use the spread operator instead

Code with Object.assign:

setFiles(acceptedFiles.map(file => Object.assign(file, {
        preview: URL.createObjectURL(file)
      })));

Trying to implement spread operator

setFiles( [{...acceptedFiles[0], ...{preview: URL.createObjectURL(acceptedFiles[0])}}] )

But i'm getting an object with just two values

{
path: "jaguar.jpg"
preview: "blob:smthing/07b56761-8d6e-4623-a4c9-377de739f52b"
}

import { Box, Typography } from '@mui/material';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { FileWithPath, useDropzone } from 'react-dropzone';
import { styled } from '@mui/system';
import Image from 'next/image';

const DropzoneBox = styled(Box)({
  display: 'flex',
  justifyContent: 'center',
  padding: 2,
  borderWidth: 1, 
  borderRadius: 2, 
  borderStyle: 'dashed'
});

const Thumb = styled('div')({
  display: 'inline-flex',
  width: 200,
  height: 100,
  padding: 4,
  boxSizing: 'border-box'
});

const ThumbsContainer = styled('aside')({
  display: 'flex',
  flexDirection: 'row',
  flexWrap: 'wrap',
});

type Props = {
  onDropChange: (file: FileWithPath) => void
}

type FileProps = FileWithPath & {
  preview: string,
}

function ImageDropZone({ onDropChange }: Props) {
  const [files, setFiles] = useState<FileProps[]>([]);
  
  const onDrop = useCallback((acceptedFiles: FileWithPath[]) => {
    onDropChange(acceptedFiles[0])
    setFiles( [{...acceptedFiles[0], preview: URL.createObjectURL(acceptedFiles[0])}] )
  }, [onDropChange])

  const { getRootProps, getInputProps } = useDropzone({
    accept: 'image/*',
    onDrop,
    maxFiles: 1
  });
  
  useEffect(() => {
    files.map(file => URL.revokeObjectURL(file.preview));
  }, [files]);

  return (
    <>
      <DropzoneBox {...getRootProps()}>
        <input {...getInputProps()} />
        <Typography sx={{ padding: 2 }}>
          Drag and drop image here, or click to select files
        </Typography>
      </DropzoneBox>
      <ThumbsContainer>
        {
          files.map(file => (
            <Thumb key={file.name}>
              <Image
                src={file.preview}
                alt="course image"
                width={150}
                height={100}
              />
            </Thumb>      
          ))
        }
      </ThumbsContainer>
    </>  
  );
}

export default React.memo(ImageDropZone)

currently you are use the setFiles( [{...acceptedFiles[0], ...{preview: URL.createObjectURL(acceptedFiles[0])}}] )

but acceptedFiles[0] is not an object, it will file, so you have to set manually like below

setFiles( [{
  name:acceptedFiles[0].name,  
  lastModified:acceptedFiles[0].lastModified,  
  lastModifiedDate:acceptedFiles[0].lastModifiedDate,  
  path:acceptedFiles[0].path,  
  size:acceptedFiles[0].size,  
  type:acceptedFiles[0].type,  
  webkitRelativePath:acceptedFiles[0].webkitRelativePath,  
  preview: URL.createObjectURL(acceptedFiles[0])
}] )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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