Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when i use this approach redux warns of a mutation on the File object's lastModifiedDate field #5

Closed
scamden opened this issue Nov 15, 2016 · 17 comments
Assignees

Comments

@scamden
Copy link

scamden commented Nov 15, 2016

I have read that you should only use primitives in the redux store and perhaps this is why? any thoughts on this?

@BBB
Copy link
Owner

BBB commented Nov 16, 2016

@scamden can you give me some more details please? What version of redux/ redux-form are you using?

Are you manipulating the files at all?

@BBB BBB self-assigned this Nov 16, 2016
@scamden
Copy link
Author

scamden commented Nov 16, 2016

absolutely, sorry for the lack of detail. we're using redux form 6.1 and redux 3.6, i'm not manipulating the files and thats what's odd. what ends up mutated is the last modified date. despite the date seemingly not changing the reference of the date object on the file object is changing. even between calling my async action creator and dispatching the action. i assumed that somehow the File object generates the date on demand or something strange like that, but would love it if there's another explanation. the reason for the error btw is our use of redux-immutable-state-invariant, i don't believe it would fail without that.

@imyagnesh
Copy link

@BBB I am getting the same issue.

i am getting following error when i upload the file second time.

Uncaught Error: A state mutation was detected between dispatches, in the path form.SkillForm.values.files.0.lastModifiedDate. This may cause incorrect behavior.

following is my code snippet

import { PropTypes } from 'react';
import Dropzone from 'react-dropzone';

const style = {
  dropZoneStyle: {
    borderWidth: '2px',
    borderColor: 'black',
    borderStyle: 'dashed',
    borderRadius: '4px',
    padding: '30px',
    width: '100%',
    transition: 'all 0.5s',
  },
  innerDropZoneStyle: {
    textAlign: 'center',
  },
};

const DropzoneInput = (field) => {
  const files = field.input.value;
  return (
    <div>
      <Dropzone
        name={field.name}
        onDrop={(filesToUpload, e) => {
          const acceptedFiles = [ ...filesToUpload ];
          field.input.onChange(acceptedFiles);
        }}
        style={style.dropZoneStyle}
      >
        <p style={style.innerDropZoneStyle}>Drop an image or click to select a file to upload.</p>
      </Dropzone>
      {field.meta.touched &&
    field.meta.error &&
    <span className="error">{field.meta.error}</span>
  }
  {
  files && Array.isArray(files) && (
    <ul>
      {files.map((file, i) => <li key={i}>{file.name}</li>)}
    </ul>
  )
  }
    </div >
  );
};

DropzoneInput.propTypes = {
  field: PropTypes.object,
};

export default DropzoneInput;

@scamden
Copy link
Author

scamden commented Dec 8, 2016 via email

@BBB
Copy link
Owner

BBB commented Dec 8, 2016

@yagneshmodh I'd suggest making an issue with the redux-immutable-state-invariant it seems like it is the root of your issue.

@ifranke
Copy link

ifranke commented Dec 9, 2016

See the same problem with redux-immutable-state-invariant in file type input. Problem occurs in any variations with DropZone or with simple file input...

@BBB BBB closed this as completed Feb 17, 2017
@dannymcpherson
Copy link

Is the primitive only version sufficient for uploading the file?

@scamden
Copy link
Author

scamden commented Mar 21, 2017

@dannymcpherson it's not. i send the real file to an action where it begins the upload but stores only the primitive version in state

@jhonatasobrinho
Copy link

Any new implementation regarding this issue? I tried almost every solution to this but none of them worked :(

@linde12
Copy link

linde12 commented Feb 19, 2018

Actually i think this is valid. I don't think it's redux-immutable-state-invariant's fault either.

It looks like lastModifiedDate is being "changed" (the date is the same but the reference points to another Date instance) in the File which is why redux-immutable-state-invariant is saying that someone mutated state.

File.lastModifiedDate is deprecated and is never equal to itself (file.lastModifiedDate === file.lastModifiedDate // always false) that's why redux-immutable-state-invariant complains about it being mutated. I still think it should be handled by redux-form though.

Maybe redux-form can have explicit support for handling files. Putting the File instances in the store, IMHO, is a nasty thing to do either way.

@AuthorProxy
Copy link

AuthorProxy commented May 21, 2018

So any workarounds? Now only is ignoring at redux-immutable-state-invariant works for me.

@gss-patricia
Copy link

I've the same issue._

@vonkanehoffen
Copy link

@AuthorProxy @gss-patricia as mentioned here: leoasis/redux-immutable-state-invariant#38 you can set redux-immutable-state-invariant to ignore the node of your redux store containing the file. Just init it with the relevant path. Something like:

const middleware = immutableStateInvariantMiddleware({
            ignore: [
                'wherever.your.storing.your.file',
            ]
        })

@AuthorProxy
Copy link

AuthorProxy commented Jul 9, 2018

@gss-patricia @vonkanehoffen

yes it's ok for one simple form, but I should write something like this for forms with dynamic fields:

form.trip-edit-expenses.values.expenses[1].receiptFileBlob
form.trip-edit-expenses.values.expenses[2].receiptFileBlob
form.trip-edit-expenses.values.expenses[3].receiptFileBlob
form.trip-edit-expenses.values.expenses[4].receiptFileBlob
form.trip-edit-expenses.values.expenses[5].receiptFileBlob

and because form has dynamic fields and redux-immutable-state-invariant doesn't support regex, I should write something like this: form.trip-edit-expenses.values.expenses which ignore every other field together with receiptFileBlob, which works but kill all redux-immutable-state-invariant features.

And it's just one form, I have a lot of forms which accepts files, and even if regex will be supported it's looks more like a hack then a prefereble behaviour for a common usecase

@abolognino
Copy link

instead of storing the File in the store I create an URL for the file and store that in the store

onDrop = (filesAccepted) => {
    const file = filesAccepted[0];
    const url = URL.createObjectURL(file);
    this.props.fileSelected({name: file.name, url: url}); /* this dispatches an action */
};

then when I need the actual content I simply retrieve it like this:

const blob = await fetch(file.url).then(r => r.blob());

@NwawelAIroume
Copy link

instead of storing the File in the store I create an URL for the file and store that in the store

onDrop = (filesAccepted) => {
    const file = filesAccepted[0];
    const url = URL.createObjectURL(file);
    this.props.fileSelected({name: file.name, url: url}); /* this dispatches an action */
};

then when I need the actual content I simply retrieve it like this:

const blob = await fetch(file.url).then(r => r.blob());

getting an error when trying to get the dataURL
Uncaught (in promise) TypeError: Failed to fetch

@NwawelAIroume
Copy link

@gss-patricia @vonkanehoffen

yes it's ok for one simple form, but I should write something like this for forms with dynamic fields:

form.trip-edit-expenses.values.expenses[1].receiptFileBlob
form.trip-edit-expenses.values.expenses[2].receiptFileBlob
form.trip-edit-expenses.values.expenses[3].receiptFileBlob
form.trip-edit-expenses.values.expenses[4].receiptFileBlob
form.trip-edit-expenses.values.expenses[5].receiptFileBlob

and because form has dynamic fields and redux-immutable-state-invariant doesn't support regex, I should write something like this: form.trip-edit-expenses.values.expenses which ignore every other field together with receiptFileBlob, which works but kill all redux-immutable-state-invariant features.

And it's just one form, I have a lot of forms which accepts files, and even if regex will be supported it's looks more like a hack then a prefereble behaviour for a common usecase

import {isImmutableDefault} from "@reduxjs/toolkit";
const isImmutable = (value) => isImmutableDefault(value) || value instanceof File

in the getDefaultMiddleware add this

...
immutableCheck: {
          isImmutable: isImmutable,
...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests