I am trying to upload a photo in my React application, along with some form data. It works with uploading form data from ItemAdd.jsx, a child component of ItemList.jsx. However, when I try to also POST an image file with this data, the image property is undefined
when it hits the server.
My suspicion is that I'm using the wrong content-type in the request, but I'm not sure what I should be using instead (if that is the issue here).
Parent Component - ItemList.jsx
import React from 'react';
import 'whatwg-fetch';
import classNames from 'classnames';
import ItemAdd from './ItemAdd.jsx';
export default class ItemList extends React.Component {
constructor() {
super();
this.createItem = this.createItem.bind(this);
}
createItem(newItem) {
console.log('PHOTO:', newItem.image);
fetch('/api/item', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newItem),
}).then(response => {
}).catch(err => {
});
}
render() {
return (
<div>
<ItemAdd createItem={this.createItem} />
</div>
);
}
}
Child Component - ItemAdd.jsx
import React from 'react';
export default class ItemAdd extends React.Component {
constructor() {
super();
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
image: null,
imagePreviewUrl: null
}
}
handleSubmit(e) {
e.preventDefault();
let form = document.forms.itemAdd;
this.props.createItem({
name: form.name.value,
image: this.state.image
});
// Clear the form and state for the next input.
form.name.value = "";
this.state.image = null;
this.state.imagePreviewUrl = null;
}
handleImageChange(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
image: file,
imagePreviewUrl: reader.result
});
}
reader.readAsDataURL(file)
}
render() {
let { imagePreviewUrl } = this.state;
let $imagePreview = null;
if (imagePreviewUrl) {
$imagePreview = (<img src={imagePreviewUrl} className={'img-preview'} />);
} else {
$imagePreview = (<div className="previewText">Please select an image.</div>);
}
return (
<div>
<form name="itemAdd" onSubmit={this.handleSubmit}>
<table>
<tr>
<td><label for="name">Name:</label></td>
<td><input type="text" name="name" id="name" placeholder="Name" /></td>
</tr>
<tr>
<td><input type="file" onChange={(e) => this.handleImageChange(e)} /></td>
<td>
<div className="img-preview">
{$imagePreview}
</div>
</td>
</tr>
<tr>
<td><button>Add</button></td>
</tr>
</table>
</form>
</div>
);
}
}
You might not be able to post an image as part of JSON data, calling JSON.stringify()
on an image is not a good idea.
I would recommend using formData
to submit the form, which makes it multipart/form-data
content type.
You might have to handle that differently in the backend.
Example :
createItem(newItem) {
console.log('PHOTO:', newItem.image);
const h = {}; //headers
let data = new FormData();
data.append('image', newItem.image);
data.append('name', newItem.name);
h.Accept = 'application/json'; //if you expect JSON response
fetch('/api/item', {
method: 'POST',
headers: h,
body: data
}).then(response => {
// TODO : Do something
}).catch(err => {
// TODO : Do something
});
}
You can read more on formData
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With