5

I'm trying to upload a picture using react hooks

const [picture, setPicture] = useState();

const onChangePicture = e => {
    console.log('picture: ', picture);
    setPicture(...picture, e.target.files[0]);
};

<input
  type="file"
  //style={{ display: 'none' }}
  onChange={e => onChangePicture(e)}
/>

however I'm getting the following error:

Uncaught TypeError: picture is not iterable

when I change the onChangePicture to

setPicture(picture, e.target.files[0]) 

the picture variable is undefined,

any help would be appreciated.

8
  • Unless picture is an object setPicture(e.target.files[0]) should do it. Commented Jun 17, 2019 at 10:33
  • I'm not sure it's an object or not, I set the value with useState(null), but just using setPicture(e.target.files[0]) still gives undefined Commented Jun 17, 2019 at 10:36
  • I think that It's due to the value of picture which is null. And do you think that null is iterable? Commented Jun 17, 2019 at 10:40
  • that's right but I changed the value to useState() and setPicture(e.target.files[0]) but I still get the value of picture to be undefined Commented Jun 17, 2019 at 10:42
  • 1
    @Andy now I just get picture: null in the console Commented Jun 17, 2019 at 10:50

5 Answers 5

12

For anybody arriving here looking for how to do it with TypeScript:

const [file, setFile] = useState<File>();

const onChange = (event: React.FormEvent) => {
    const files = (event.target as HTMLInputElement).files

    if (files && files.length > 0) {
        setFile(files[0])
    }
}
Sign up to request clarification or add additional context in comments.

Comments

10

I think you meant to do:

setPicture([...picture, e.target.files[0]]);

This will concatenate the first file to all current files.

Remember to use const [picture, setPicture] = useState([]); as to make sure it doesn't break the first time around

3 Comments

I get an empty array in the console picture: []
The first time you would because you're printing the console contents on the current state which is initially empty. Do you mean you get an empty array every time you add a file?
that's right only the first time I get an empty array and second time I get the correct data
7

You can pass the value directly into setPicture function to set the state variable picture.

Try:

const [picture, setPicture] = useState(null);

const onChangePicture = e => {
    console.log('picture: ', picture);
    setPicture(e.target.files[0]);
};

<input
  type="file"
  //style={{ display: 'none' }}
  onChange={onChangePicture}
/>

2 Comments

Can you change console.log line to: console.log('picture: ', e.target.files[0]); and tell the output?
Try changing the onChange to what I've written in the answer. I'm guessing the event is not being passed to the function.
0

onChange = {(e) => this.onChangePicture(e)} can only be written when you made the states as

states = {
         image,
         name
    }

but when using useState()

you need to use

const [image, setImage] = useState("");

onChange = {(e) => setImage(e.target.files[0])}

I hope this solves the error.

Comments

-2

I finally fix this issue:

Problem is here

const [picture, setPicture] = useState(null); //Incorrect

You can use this

const [picture, setPicture] = React.useState(""); //Correct 

This can fix this issue

1 Comment

You need to import useState from react

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.