11

I'm using react-dropzone to allow a user to upload a profile photo.

I define the custom CSS like so:

const dropzoneStyle = {
  width: `200px`,
  height: `200px`,
  backgroundColor: `#1DA1F2`,
};

Inside the method to render the DropZone input, I can detect if their is a file preview which is populated after a user selects an image to be uploaded..

What I want to do is, if the file.preview exists, send the file.preview the the dropzoneStyle so a background-image is added to the CSS.

const renderDropzoneInput = (field) => {
  const files = field.input.value;
  let dropzoneRef;

  if (files[0]) {
    console.log(files[0].preview)
  }

  return (
    <div>
      <Dropzone
        name={field.name}
        ref={(node) => { dropzoneRef = node; }}
        accept="image/jpeg, image/png"
        style={dropzoneStyle}
      >

How can I pass files[0].preview to the style dropzoneStyle with React?

halfer
  • 19,824
  • 17
  • 99
  • 186
AnApprentice
  • 108,152
  • 195
  • 629
  • 1,012

2 Answers2

15

I usually just define the style as an arrow function that returns the style object, and pass in whatever parameters are needed for the style. There is a shorthand notation for returning an object literal from an arrow function that works nicely for this.

const style = () => ({});

Just remember to only use ternary operators if using the shorthand, otherwise you would just need to explicitly return an object.

So, for your style:

const dropzoneStyle = (isPreview) => ({
  width: `200px`,
  height: `200px`,
  backgroundColor: `#1DA1F2`,
  backgroundImage: (isPreview) ? 'url(/path/to/image.jpg)' : 'none',
});

This adds the image is isPreview is true, but keeps it blank if not.

Then in your component, call the function where the style goes:

return (
  <div>
    <Dropzone
      {...otherProps}
      style={ dropzoneStyle(isPreview) }
    >
  </div>
);
Joe Dalton
  • 346
  • 1
  • 9
  • love this idea but it is return a console error `Warning: Failed prop type: Invalid prop `style` of type `function` supplied to `Dropzone`, expected `object`.` – AnApprentice Jun 26 '17 at 02:10
  • 1
    @AnApprentice Are you calling the style as a function, as in using `dropzoneStyle()` rather than `dropsoneStyle`? – Joe Dalton Jun 26 '17 at 02:20
  • I think the issue was react-dropzone has proptypes defined and wants style to be an object not a function – AnApprentice Jun 26 '17 at 02:22
  • 1
    Oh, right. Well, if you need to use logic in your styles elsewhere, I think this is a pretty clean way. – Joe Dalton Jun 26 '17 at 02:25
  • totally agree. I wish I could use it here. Thank you again for the help!! – AnApprentice Jun 26 '17 at 02:25
  • @JoeDalton. Hi, your solution came to my help too. Just I need to ask one more thing. Is it possible to add CSS property for first-child or nth-child using this variable styled? Something like, `span:first-child { border-radius: 15px 0 0 15px }` ? – program_bumble_bee Oct 22 '20 at 17:49
9

Assuming files[0].preview returns a file (image) URL, you should be able to set a new style and pass it to the Dropzone component.

Something along these lines:

const renderDropzoneInput = (field) => {
  const files = field.input.value;
  let dropzoneRef;

  render() {
    let dropzoneStyle = {
      width: `200px`,
      height: `200px`,
      backgroundColor: `#1DA1F2`,
    };

    if (files[0]) {
      dropzoneStyle = {
        width: `200px`,
        height: `200px`,
        backgroundColor: `#1DA1F2`,
        backgroundImage: `url(${files[0].preview})`,
        // or to use a fixed background image
        // backgroundImage: `url(/path/to/static/preview.png)`,
        backgroundPosition: `center center`,
        backgroundRepeat: `no-repeat`
      };
    }

    return (
      <Dropzone
        name={field.name}
        ref={(node) => { dropzoneRef = node; }}
        accept="image/jpeg, image/png"
        style={dropzoneStyle}
      />
    )
  }
}  

a spread operator could be used to DRY this code a bit, with:

let dropzoneStyle = {
  width: `200px`,
  height: `200px`,
  backgroundColor: `#1DA1F2`,
};

if (files[0]) {
  dropzoneStyle = {
    ...dropzoneStyle,
    backgroundImage: `url(/path/to/static/preview.png)`,
    backgroundPosition: `center center`,
    backgroundRepeat: `no-repeat`
  };
}
Brett DeWoody
  • 59,771
  • 29
  • 135
  • 184