GithubHelp home page GithubHelp logo

vutoan266 / react-images-uploading Goto Github PK

View Code? Open in Web Editor NEW
316.0 3.0 51.0 3.12 MB

The simple images uploader applied Render Props pattern that allows you to fully control UI component and behaviors.

Home Page: https://github.com/vutoan266/react-images-uploading

License: MIT License

JavaScript 19.13% TypeScript 76.85% HTML 0.93% Shell 2.25% Dockerfile 0.83%
react react-images-uploading image upload uploader images image-upload reactjs typescript react-images-upload

react-images-uploading's Introduction

react-images-uploading

The simple images uploader applied Render Props pattern. (You can read more about this pattern here).

This approach allows you to fully control UI component and behaviours.

See the intro blog post

tested with jest Github_Actions NPM NPM License: MIT PRs Welcome Package Quality code style: prettier

All Contributors

Package Quality

Installation

npm

npm install --save react-images-uploading

yarn

yarn add react-images-uploading

Usage

You can check out the basic demo here:

Basic

import React from 'react';
import ImageUploading from 'react-images-uploading';

export function App() {
  const [images, setImages] = React.useState([]);
  const maxNumber = 69;

  const onChange = (imageList, addUpdateIndex) => {
    // data for submit
    console.log(imageList, addUpdateIndex);
    setImages(imageList);
  };

  return (
    <div className="App">
      <ImageUploading
        multiple
        value={images}
        onChange={onChange}
        maxNumber={maxNumber}
        dataURLKey="data_url"
      >
        {({
          imageList,
          onImageUpload,
          onImageRemoveAll,
          onImageUpdate,
          onImageRemove,
          isDragging,
          dragProps,
        }) => (
          // write your building UI
          <div className="upload__image-wrapper">
            <button
              style={isDragging ? { color: 'red' } : undefined}
              onClick={onImageUpload}
              {...dragProps}
            >
              Click or Drop here
            </button>
            &nbsp;
            <button onClick={onImageRemoveAll}>Remove all images</button>
            {imageList.map((image, index) => (
              <div key={index} className="image-item">
                <img src={image['data_url']} alt="" width="100" />
                <div className="image-item__btn-wrapper">
                  <button onClick={() => onImageUpdate(index)}>Update</button>
                  <button onClick={() => onImageRemove(index)}>Remove</button>
                </div>
              </div>
            ))}
          </div>
        )}
      </ImageUploading>
    </div>
  );
}

Validation

...
  {({ imageList, onImageUpload, onImageRemoveAll, errors }) => (
    errors && <div>
      {errors.maxNumber && <span>Number of selected images exceed maxNumber</span>}
      {errors.acceptType && <span>Your selected file type is not allow</span>}
      {errors.maxFileSize && <span>Selected file size exceed maxFileSize</span>}
      {errors.resolution && <span>Selected file is not match your desired resolution</span>}
    </div>
  )}
...

Drag and Drop

...
  {({ imageList, dragProps, isDragging }) => (
    <div {...dragProps}>
      {isDragging ? "Drop here please" : "Upload space"}
      {imageList.map((image, index) => (
        <img key={index} src={image.data_url} />
      ))}
    </div>
  )}
...

Props

parameter type options default description
value array [] List of images
onChange function (imageList, addUpdateIndex) => void Called when add, update or delete action is called
dataURLKey string dataURL Customized field name that base64 of selected image is assigned to
multiple boolean false Set true for multiple chooses
maxNumber number 1000 Number of images user can select if mode = multiple
onError function (errors, files) => void Called when it has errors
acceptType array ['jpg', 'gif', 'png'] [] The file extension(s) to upload
maxFileSize number Max image size (Byte) and it is used in validation
resolutionType string 'absolute' | 'less' | 'more' | 'ratio' Using for image validation with provided width & height
resolutionWidth number > 0
resolutionHeight number > 0
inputProps React.HTMLProps<HTMLInputElement>
allowNonImageType boolean false Using for uploading non-image type purpose (E.g. txt, pdf, heic, ...)

Note

resolutionType

value description
absolute image's width === resolutionWidth && image's height === resolutionHeight
ratio (resolutionWidth / resolutionHeight) === (image width / image height)
less image's width < resolutionWidth && image's height < resolutionHeight
more image's width > resolutionWidth && image's height > resolutionHeight

Exported options

parameter type description
imageList array List of images to render.
onImageUpload function Called when an element is clicks and triggers to open a file dialog
onImageRemoveAll function Called when removing all images
onImageUpdate (updateIndex: number) => void Called when updating an image at updateIndex.
onImageRemove (deleteIndex: number | number[]) => void Called when removing one or list image.
errors object Exported object of validation
dragProps object Native element props for drag and drop feature
isDragging boolean "true" if an image is being dragged

Contributors ✨

Thanks goes to these wonderful people (emoji key):


vutoan266

💻 🤔 📖 🚧 ⚠️ 👀

David Nguyen

💻 🤔 📖 👀

DK

💻 🚇 🤔 👀 📖

Isaac Maseruka

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

react-images-uploading's People

Contributors

allcontributors[bot] avatar asminbudha avatar conandk avatar davidnguyen11 avatar dependabot[bot] avatar masesisaac avatar vutoan266 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

react-images-uploading's Issues

upload to API accept multipart/form-data instead of application/json

Hi team,
Sorry again for one questions
The library once choice will send as in json format:
uploads: Array(2) 0: data_url: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD" file: File lastModified: 1604325396020 lastModifiedDate: Mon Nov 02 2020 14:56:36 GMT+0100 (中歐標準時間) {} name: "4.jpg" size: 83005 type: "image/jpeg" webkitRelativePath: ""

Will it possible add any parametre to change to multipart/form-data instead of application/json ?

Appreciate your help

How to set images by default in value

I need to made a modify page so i fetch image from api and i want to set it by default in value of the ImageUploading componement. I get this error :
Uncaught TypeError: Failed to construct 'Image': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
Is there a way to set images by default for ImageUploading ?

Multiple image upload broken in some cases

This issue also occurs in the sandbox demo. Tested on Android (smarthpone and tablet).

When you click to upload images and the native upload module appears, you can choose 'Browse'. Then, on top, you can choose Google Drive, Google Photos, ... When you click Google Photos and try to upload multiple images, only the last image selected gets uploaded.

no support for existing (uploaded) images

Great component, and love the way its entirely removed from UI concerns. But I'm struggling to use it in the context of having previously uploaded images that are now stored away - i.e. not dataURLs any longer but .png or .jpg on disk for web-serving.

I've tried passing in an array of existing images to "defaultValue", but of course it doesn't understand my array - I suspect it expects an array of dataURLs. I am passing an array of objects, one field of which is the relative URL for the file (another being the size, another being the date of upload, etc).

not sure what the solution would be, but I imagine if "defaultValue" could support a list of fully qualified urls, plus some kind of unique reference field (id) for indexing to replace/delete, this would be a start?

Errors on UseRef$1 and Invariant Violation

Hi there, first of all, thank you for building out this library as it will be a great help!

I'm basically copying your Example component and trying to see if it works on my app. I'm getting these errors and the component does not show up at all. Just wondering if I don't have the right requirements to use this.

I'm on React version 15.5.4. Not sure if that matters. What am I doing wrong?

Screen Shot 2020-05-06 at 11 08 39 PM

3.1.2 not building with react ^17.0.1

Hi,

When I make a build the component is not showing anything on the final build (just an input file with display none).
I tried to downgrade to 3.0.1 and the build seems to be working fine.

I'm in a hurry so I can test anymore right now.

This is not working

{
  "name": "clientappname",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "axios": "^0.20.0",
    "node-sass": "^4.14.1",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-helmet": "^6.1.0",
    "react-images-uploading": "^3.1.2",
    "react-scripts": "3.4.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

this is working

{
  "name": "seln-postal",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "axios": "^0.20.0",
    "node-sass": "^4.14.1",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-helmet": "^6.1.0",
    "react-images-uploading": "^3.0.1",
    "react-scripts": "3.4.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Get FileList Object from ImageUploading component

Is it possible to get the FileList object itself from the ImageUploading component? Such as from the 'onChange' method or using a 'ref' attribute. I would like to extract the FileList object and pass it to my submit method. My efforts at building an object to mimic it and pass it on to my submit function have been unsuccessful for far. I can create an object but my backend expects a FileList and so the submission fails.

  let files;
  const onChange = (imageList) => {
    setImages(imageList);
    files = {};
    let index = 0;
    imageList.forEach((image) => {
      files[index] = image.file;
      index += 1;
    });
    // my files object above is not recognized as a FileList Object

UPDATE

Using a Map Object I was able to mimic the functionality of the FileList as follows:

  const files = [];
  const onChange = (imageList) => {
    setImages(imageList);
    imageList.forEach((image) => {
      files.push(image.file);
    });

   const FilesMap = new Map();
    let index = 0;

   files.forEach((file) => {
     FilesMap.set(file, [`variables.yourImageUrl.${index}`]);
     index += 1;
   });

However, it would be great if a callback was made available in this awesome package to simply this.

DefaultValue

Hi is there anyway to set default value for this component?

[Feature Request] Require Drag and Drop support for uploading images

Thanks for creating this great library.

In my current project, I need a feature where in the user should be able to drop files on a target to upload files. I tried to implement drag and drop feature myself, but I couldn't find a way to update the images list with the dropped files. So It would be great If you could expose some prop for doing this.

Also, It would be awesome if this library itself provides drag and drop image upload support.

Thanks.

acceptType is case sensitive

acceptType attribute is case sensitive, which is a bit bad user experience for users who upload files with extension JPG or PNG.

A quick fix is to include uppercase extensions, like

acceptType={['jpg', 'png', 'jpeg', 'JPG', 'PNG', 'JPEG']}

But extension comparison should be case insensitive by default and allow case sensitive checking by a boolean Prop like

acceptType={['jpg', 'png', 'jpeg']}
isCaseSensitive={true}

Let me know if this makes sense, I would love to contribute.

OnChange element can't catch element?

I'm trying to do something like this

const onChange(image, e)=>
{
 //"e" is undefined;
}

<ImageUploading defaultValue={[{dataURL:Image}]} onChange={(e)=>onChange(e)} multiple={false} />

Any thoughts? why I can't get the element ? to do something like e.target.?

upgrade libs version

Upgrading version of libraries which are being used in this component such as webpack, sinon, ... for security concerns

Video support

Hello,
In my recent project, I need to upload videos too. I used this library in one of my previous project and liked it. So I will fork and try to implement video file support. Are you interested in this? @vutoan266

Removed images cannot be re-added

First, thanks for this package! nicely done :)

The error I'm seeing ( which might be considered a feature in some cases ) is that if you add 1 image, then remove it, you cannot re-add that same image ( when selecting a single image at a time ).

The error can be repro-ed on the demo page ( add 1 image, remove it, try to re-add it ).

In my app ( where users are uploading a profile pic ) this could be confusing if someone changes their mind and then can't re-add an image.

Default value can be set only once

Hello,

Great component that separate UI and logic :)

But I'm experience issue with the defaultValue attribute : it can be set only once. After the first initialisation the preview does not change, so I force the component to recreate by setting key={defaultValue} which is bad for performance concern.
Is there a proper workaround or is this a bug ?

Regards

Support for HEIC Images

I am unable to upload .heic images despite setting my acceptType as such:

acceptType={["jpg", "gif", "png", "JPG", "heic"]}

If there is something else I have to do to support this file type I would love some suggestions. Otherwise if this is not implemented in this component, I'd love for it to be.
HEIC is the standard image type for iOS devices, so it would be awesome to have this file extension supported!

Preview of uploaded images don't show up

After uploading images when you go back again to upload images then the preview of images to be uploaded don't show up.
What I felt was that the code to show the preview don't render again because in console.log the imageList shows up to be empty

Note : Images do get uploaded on submitting.

Update docs readme

  • Brief introduction
  • Logo if it has
  • Installation
  • Usage: provides links to codesandbox with JS & TS, Server side & snippet of code
  • Development: provides commands to start dev env or production env
  • Props

Question: Image uploade filename and progress

Hey,

I am not sure how this image uploader is working.
As far as I understood the image is just base64 encoded and then I would sent it to my endpoint. Now some hq picture can be 100mb+ in size so I was wondering if it would be possible to intercept the image upload progress. Also I couldn't find the image name in the image types, is there an easy way of getting the image filename ?

Edit: Image name is under image.file.name my bad

Regards Artur

How to use for submit for images data

Hi Team
This is great library, somehow in the doc I do not see any prop for submitting ?
For example once images all selected, I add submit button allow to send post to API
But looking for document there's no relative Props ?

I used react final form to submit formulair
`import React from 'react';
import ImageUploading from "react-images-uploading";
import useAnnonces from 'service/hooks/useAnnonces';
import {Field, Form} from 'react-final-form';

export function ImageUpload() {
const [images, setImages] = React.useState([]);
const [isUpload, setIsUpload] = React.useState(false);
const maxNumber = 10;
const onChange = (imageList, addUpdateIndex) => {
// data for submit
console.log(imageList, addUpdateIndex);
setImages(imageList);
setIsUpload(true);
};

const ImgUploadAdapter = ({ input, values, ...rest }) => (
    <ImageUploading
        {...input}
        {...rest}
        multiple
        value={images}
        onChange={onChange}
        maxNumber={maxNumber}
        dataURLKey="data_url"
        imgExtension={[".jpg", ".gif", ".png", ".gif"]}
    >
        {({
              imageList,
              onImageUpload,
              onImageRemoveAll,
              onImageUpdate,
              onImageRemove,
              isDragging,
              dragProps,
              errors
          }) => (
            // write your building UI
            <div className="upload__image-wrapper">
                <button
                    className="upload bg-orange-500 text-white px-4 py-2 rounded shadow mr-1 mt-2"
                    onClick={onImageUpload}
                    {...dragProps}
                >
                    Telecharger ici
                </button>
                &nbsp;
                {imageList.length > 0 ? (
                    <button className="upload bg-gray-600 text-white px-4 py-2 rounded shadow mr-1 mt-2" onClick={onImageRemoveAll}>Supprimer toutes</button> ) :( null
                )}
                <div className="ImagelistPart flex flex-wrap mt-2">
                    {imageList.map((image, index) => (
                        <div key={index} className="image-item w-full px-3 flex-1">
                            <img src={image["data_url"]} />
                            <div className="image-item__btn-wrapper">
                                <button className="upload text-2xl text-gray-600 mr-1 mt-2" onClick={() => onImageUpdate(index)}><i class="fas fa-pen-square"></i></button>
                                <button className="uploadRemove text-2xl text-gray-600 mr-1 mt-2" onClick={() => onImageRemove(index)}><i class="fas fa-window-close"></i></button>
                            </div>
                        </div>
                    ))}
                </div>

            </div>
        )}
    </ImageUploading>
)

const {
    addPhoto
} = useAnnonces();

const onSubmit = async (values) => {
    try {
        let {
            ...payload
        } = values;

        const data = {...payload};
        //await addPhoto(data);
        console.log("photo_data", data);
    } catch (err) {
        console.log(err);
        alert('Impossible de créer annonce, merci de constacter notre equipe');
    }
}
return (
    <div className="blockUploadImage">
        <Form
            initialValues={{
                uploads: [],
            }}
            onSubmit={onSubmit}
            render={({handleSubmit, form, submitting, values}) => (
                <form onSubmit={handleSubmit}>
                    <div>
                        <Field
                            name="uploads"
                            type="file"
                            //value={values.uploads}
                            component={ImgUploadAdapter}
                        />
                    </div>
                    {isUpload ? (
                        <button
                            className="bg-orange-500 text-white active:bg-grey-500 text-sm font-bold uppercase px-12 py-4 my-4 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150"
                            type="submit"
                            disabled={submitting}

                        >
                            <i className="fas fa-paper-plane text-base mr-1 animate-bounce"></i> ENVOYER
                        </button> ) : (null)
                    }
                </form>
            )}
        />
    </div>
);

}

export default ImageUpload;
`

Thanks

paramater onError at props

Hello,

Can I get error value at props parameter like onError than at exported options? Because sometimes we need to get have custom error like with popup or modal or alert than just free text.

Thank you,
Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.