Reputation: 75
I'm trying to place the image's URL uploaded by the user into an array followed by displaying that image in the view. With my code, all I get is an empty []
in the console. Why won't any image URLs go in the array and then display that image in my view?
JS state and function
this.state = {
selectedFile: null,
previewImgURL: '',
pictures: []
};
this.imageUpload = this.imageUpload.bind(this);
}
imageUpload(e) {
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
selectedFile: file,
previewImgURL: reader.result,
pictures: [...this.state.previewImgURL, this.state.previewImgURL]
});
};
if (file) reader.readAsDataURL(file); // Allows user to preview image uploaded
this.setState(() => ({file}));
console.log(this.state.pictures); // in console, all I get's an empty []
}
JSX code:
<div className="inputWrapper">
<input
id="new_post_image"
name="post_image"
className="button is-success is-outlined"
type="file"
style={{display: 'none'}}
onChange={this.imageUpload}
accept="image/*"
/>
<label className="button is-success is-outlined" htmlFor="new_post_image">Upload</label>
</div>
{
this.state.pictures.map(key => (
<div className="uploaded-pics">
<Feed src={this.state.previewImgURL[key]} key={key} />
</div>
))
}
</div>
Here is Feed.js:
import React from 'react';
import './Feed.scss';
const feed = (props) => {
return (
<div className="row">
<div className="col-md-6 col-sm-6">
<img src={props.src}/>
</div>
</div>
);
};
export default feed;
Upvotes: 0
Views: 58
Reputation: 26
I think the issue lies within the line where you're actually adding the pictures to the state.
this.setState({
selectedFile: file,
previewImgURL: reader.result,
----> pictures: [...this.state.previewImgURL, this.state.previewImgURL]
});
When you're using the spread operator, you don't actually have this.state
yet so the this.state.previewImgURL
doesn't exist yet.
I would just try:
this.setState({
selectedFile: file,
previewImgURL: reader.result,
pictures: [reader.result]
});
I'm also not sure of the usage of the ...
(spread) syntax within that context. If you wanted to just update the pictures part of the state (given you already have state) you can use it as:
this.setState({
...this.state,
pictures: [reader.result]
});
Another thing worth noting is you're updating the state within a callback so it won't be guaranteed to be populated when you call your console.log(this.state.pictures)
Also, you're within the same cycle so your state hasn't been updated.
For extra debugging, put some sort of debugger somewhere in the Chrome DevTools and in the console type this.state.picture
. This will display the pictures part of the state and in the debugger you will also be able to step over your program.
Go here for more info on DevTools debugging: https://developers.google.com/web/tools/chrome-devtools/javascript/
Upvotes: 1
Reputation: 3451
Have quick read up on React Documentation of setState.
If you console.log(this.state)
right after a setState, you're still inside the old cycle, where the states are still the old value.
After the state change, render
gets triggered, and if you log this.state
there, you will be able to see your updated states.
Another way of immediately accessing an updated state is by using a callback as 2nd argument of setState
:
reader.onloadend = () => {
this.setState({
selectedFile: file,
previewImgURL: reader.result,
pictures: [...this.state.previewImgURL, this.state.previewImgURL]
}, () => {
console.log(this.state.pictures) // this should show you the latest state
});
};
Upvotes: 0