I use the fetch API to send a put request with images, everything works up until the image. It says the following on the image fields:
Cannot read properties of undefined (reading 'value')
I assume I'm missing something.
const createPost = async (e) => {
e.preventDefault();
let formData = new FormData()
formData.append("author", userid)
formData.append("needed_image", e.target.neededimage.value)
formData.append("wanted_image", e.target.wantedimage.value)
const response = await fetch('http://127.0.0.1:8000/api/createpost/', {
method: "POST",
body: formData
})
}
input fields
<div>
<input type="file" accept="image/*" name="neededimage" id="file" />
<input type="file" accept="image/*" name="wantedimage" id="file2"/>
</div>
You can add state to store file and your change function something like that:
const [files, setFiles] = React.useState({
neededimage: '',
wantedimage: ''
});
const addImage = (e) => {
setFiles((files) => {
return { ...files, [e.target.name]: e.target.files[0] };
});
};
Add onChange for your inputs:
<form>
<input
type="file"
accept="image/*"
name="neededimage"
id="file"
onChange={addImage}
/>
<input
type="file"
accept="image/*"
name="wantedimage"
id="file2"
onChange={addImage}
/>
</form>
And then append files from state into you formData.
You're trying to access value, perhaps what you wanted to do is to access the files.
<div>
<input type="file" accept="image/*" name="neededimage" id="file" />
</div>
With the above input tags, you can access the files property which is an IMMUTABLE array.
const createPost = async (e) => {
e.preventDefault();
let formData = new FormData();
formData.append("needed_image", e.target.files[0]);
const response = await fetch('http://127.0.0.1:8000/api/createpost/', {
method: "POST",
body: formData
});
};
Again remember that this array is IMMUTABLE therefore you can't modify the content directly. Also the e.target.files[0] is stored as a buffer therefore the returned data is a buffer stored in the formData.
Now as you said you have multiple input to deal with, so in this it is better to create a change handler and attach it both the inputs and use an outer FormData to append.
<div>
<input type="file" accept="image/*" name="neededimage" id="neededimage" />
<input type="file" accept="image/*" name="wantedimage" id="wantedimage" />
</div>
const neededImage = document.getElementById('neededimage');
const wantedImage = document.getElementById('wantedimage');
const handleFiles = () => {
const files = [...fileInput.files];
console.log(selectedFiles);
}
neededimage.addEventListener("change", handleFiles);
wantedImage.addEventListener("change", handleFiles);
One more thing since you want to upload multiple files it is better to allow them all in one input.
<div>
<input type="file" multiple accept="image/*" name="images" id="images" />
</div>
function uploadMultipleFiles() {
const formData = new FormData();
const file = document.getElementById("images") // all uploaded files
for (let i = 0; i < file.files.length; i++) {
formData.append(`image-${i}`, file.files[i]);
}
}```