Mulitple image add in react js - reactjs

I am working on a project where I have one page where you should be able to add images. One by one it's worked perfectly. Now I want to make to be able to multiple add and upload. I don't want to use any library for image upload.
const onFileChange = (e) => {
const reader = new FileReader();
reader.onload = () => {
if (reader.readyState === 2) {
setPreview(reader.result);
}
};
reader.readAsDataURL(e.target.files[0]);
if (e.target.files[0]) {
setOver(true);
}
const copy = [...image];
copy.push(e.target.files[0]);
setImage([...copy]);
};
const onFileUpload = () => {
const formdata = new FormData();
image.forEach((elem) => {
formdata.append("data", elem);
});
formdata.append("id_grobnog_mjesta", Id);
addImage(formdata);
};
const addImage = async (data) => {
try {
setIsLoading(true);
const response = await apiRequest({
method: "post",
url: `spisak-srebrenica/upload`,
headers: {
Authorization: `Bearer ${token}`,
},
data,
});
if (response.data.success) {
getVictimImage();
}
setIsLoading(false);
setImage([]);
} catch (err) {
setIsLoading(false);
setImage([]);
}
};
Upload component :
<Upload>
<BiImageAdd size={50} opacity={0.5} />
<input type="file" onChange={onFileChange} />
<div className="items">
<p>Dodajte sliku</p>
<span className="format">PNG,JPG,GIF do 10MB</span>
</div>
</Upload>

add multiple attribute
<input type="file" id="files" name="files" multiple>
https://www.w3schools.com/tags/att_input_multiple.asp

Related

Graph Api Video Publish to Facebook Page not Working

I am trying to make an application that allows user to upload images and videos posts to the facebook page by uploading them to the application.
My access token and all other stuffs are working fine for uploading pictures, but not for videos.
const [file, setFile] = useState([]);
code for uploading picture (working)
const formData = new FormData();
formData.append("source", file)
axios.post("https://graph.facebook.com/<pageId>/photos?",
formData,
{
headers:
{
"Content-Type": "multipart/form-data",
"Authorization": "Bearer <access_token>"
}
}
).then(
(res) => {
if (res.data["id"]) {
alert("Upload Successfully")
}
}
).catch((err) => {
alert("Error communicating to server")
console.log(err)
})
code for uploading video (not working)
const formData = new FormData();
formData.append("file", file);
axios.post("https://graph-video.facebook.com/v16.0/<page_id>/videos",
formData,
{
headers:
{
"Content-Type": "multipart/form-data",
"Authorization": "Bearer <same_access_token>"
}
}
).then(
(res) => {
if (res.data["id"]) {
alert("Upload Successfully")
}
}
).catch((err) => {
alert("Error communicating to server")
console.log(err)
})
code for getting input
<input className="btn" type="file" accept="video/mp4,video/x-m4v,video/*"
onChange=
{
(e) => { handleChange(e) }
}
/>
<input className="btn" type="file" accept="image/png, image/jpeg"
onChange=
{
(e) => { handleChange(e) }
} />
const handleChange = (e) => {
setFile(e.target.files[0]);
}

Stop react redirecting before API call has finsished

Im writing an application using react and django rest. I am trying to update a post and then redirect back to the home screen, but sometimes the redirect happens before the put request.
As there is a Get request on the home page, that then gets called first and i do not see the updated values unless i refresh the page? Any suggestions?
Here is the page with the put request (updateNote())
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { ReactComponent as ArrowLeft } from "../assets/arrow-left.svg";
const NotePage = ({ match, history }) => {
let noteId = match.params.id;
let [note, setNote] = useState(null);
useEffect(() => {
getNote();
}, [noteId]);
let getNote = async () => {
let response = await fetch(`/api/get-note/${noteId}/`);
let data = await response.json();
setNote(data);
};
let updateNote = async () => {
fetch(`/api/get-note/${noteId}/update/`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(note),
});
};
let deleteNote = async () => {
fetch(`/api/get-note/${noteId}/delete/`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
});
history.push("/");
};
let handleSubmit = () => {
updateNote().then(history.push("/"));
};
let handleChange = (value) => {
setNote((note) => ({ ...note, body: value }));
console.log("Handle Change:", note);
};
return (
<div className="note">
<div className="note-header">
<h3>
<ArrowLeft onClick={handleSubmit} />
</h3>
<button onClick={deleteNote}>Delete</button>
</div>
<textarea
onChange={(e) => {
handleChange(e.target.value);
}}
value={note?.body}
></textarea>
</div>
);
};
export default NotePage;
Then here is the page it redirects to
import React, { useState, useEffect } from "react";
import ListItem from "../components/ListItem";
const NotesListPage = () => {
let [notes, setNotes] = useState([]);
useEffect(() => {
getNotes();
}, []);
let getNotes = async () => {
let response = await fetch("/api/get-notes/");
let data = await response.json();
setNotes(data);
};
return (
<div className="notes">
<div className="notes-header">
<h2 className="notes-title">☶ Notes</h2>
<p className="notes-count">{notes.length}</p>
</div>
<div className="notes-list">
{notes.map((note, index) => (
<ListItem key={index} note={note} />
))}
</div>
</div>
);
};
export default NotesListPage;
I want to make sure that history.push("/") doesnt get executed unitll the fetch request has returned a response
I suggest using the promise method and using '.then' or await just like that :
let updateNote = async () => {
let temp =await fetch(`/api/get-note/${noteId}/update/`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(note),
});
if(temp)
history.push("/")
};
If you want to navigate after the fetch request has resolved then the code needs to wait for them to settle. Don't forget to catch and/or handle any errors and rejected Promises appropriately.
Example:
const updateNote = async () => {
// return Promise to chain from
return fetch(`/api/get-note/${noteId}/update/`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(note),
});
};
const deleteNote = async () => {
try {
// wait for Promise to resolve
await fetch(`/api/get-note/${noteId}/delete/`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
});
history.push("/");
} catch(error) {
// log error, etc...
}
};
const handleSubmit = () => {
// pass a callback in .then
updateNote()
.then(() => history.push("/"))
.catch(error => {
// log error, etc...
});
};

Image upload in mern stack using multer not working

I'm trying to upload image in MongoDB using multer and react but I'm unable to post it. I have three inputs in by form i.e title, content and image. If I try to post title and content only it is successfully being posted. I have also added "proxy": "http://localhost:8000", in frontend package.json file
Here is my form
function PostCreate() {
const [title, setTile] = useState("");
const [content, setContent] = useState("");
const [image, setImage] = useState({});
const dispatch = useDispatch();
const post = useSelector((state) => state.postReducer);
const fileOnChange = (e) => {
setImage(e.target.files[0]);
};
const submitPost = (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("image", image);
dispatch(createPost(title, content, image));
};
return (
<div className="postCreate">
<h3 className="postCreate__heading">Create New Post</h3>
<div className="formBody">
<form onSubmit={submitPost}>
<div className="formInputs">
<label className="label">Title</label>
<input
className="titleInput"
type="text"
value={title}
onChange={(e) => setTile(e.target.value)}
placeholder="Enter the Title of the Post"
/>
</div>
<div className="formInputs">
<input type="file" onChange={fileOnChange} />
</div>
<div className="formInputs">
<label className="label">Content</label>
<textarea
className="titleInput"
type="text"
style={{
width: "1500px",
height: "500px",
color: "black",
outline: "none",
border: "none",
borderRadius: "6px",
}}
value={content}
onChange={(e) => setContent(e.target.value)}
/>
</div>
<div className="button">
<Button type="submit" variant="contained" color="primary">
Post
</Button>
</div>
{/* <button type="submit">Post</button> */}
</form>
Here is my action
export const createPost = (title, content, image) => async (dispatch) => {
try {
dispatch({ type: POST_POST_LOADING });
const config = { headers: { "Content-Type": "application/json" } };
const { data } = await axios.post(
"/api/newpost",
{ title, content },
config
);
dispatch({
type: POST_POST_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: POST_POST_FAIL,
payload: error,
});
}
};
Here is my postController
const createPost = async (req, res) => {
const { title, content, writer, comment, image } = req.body;
const fileType = req.file.mimetype.split("/")[1];
const newFileName = req.file.filename + "." + fileType;
fs.rename(
`uploads/images/${req.file.filename}`,
`uploads/images/${newFileName}`,
(req, res) => {
console.log("Renamed");
}
);
// const imageUrl = req.file.filename;
const newPost = await Post.create({
title,
content,
writer,
comment,
image,
// imageUrl,
});
if (newPost) {
res.send("Post created");
console.log("Post created");
} else {
res.status(201).send("Post not created");
console.log("Post not created");
}
};
Here is my routes
router.post("/newpost", upload.single("image"), createPost);
You're creating a form, which is a good start, but not sending it with axios.
To send a file from frontend to backend, you need to construct a form using FormData API and append the file to it. You can also append additional data to it.
Here is how I would change your code to work. In your form file:
const formData = new FormData();
formData.append('image', image);
formData.append('title', title);
formData.append('content', content);
dispatch(createPost(formData));
Then change your action to:
export const createPost = (formData) => async (dispatch) => {
try {
dispatch({ type: POST_POST_LOADING });
const config = { headers: { "Content-Type": "multipart/form-data" } };
const { data } = await axios.post(
"/api/newpost",
formData,
config
);
dispatch({
type: POST_POST_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: POST_POST_FAIL,
payload: error,
});
}
};

Cannot save image with multer and react

I'm trying to send some string and an image to my db from a form in React component. Everything is saved, also the image name, but the file is not in the pubblic/images folder. My req.file is alway undefined and my data always an empty object
This is the Multer middleware
//Multer
const path = require("path");
const multer = require("multer");
const store = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "public/images");
},
filename: function (req, file, cb) {
cb(null, Date.now() + path.extname(file.originalname));
},
});
//Upload parameters
const upload = multer({
storage: store,
});
this is the post request of node
router.post("/", upload.single("image"), verify, async (req, res, next) => {
console.log(req.file);
const book = new Book({
title: req.body.title,
author: req.body.author,
image: req.body.image,
});
try {
const savedBook = await book.save();
res.send(savedBook);
} catch (error) {
res.send(error);
}
});
React
const token = useSelector((state) => state.token.token);
const data = new FormData();
//set Cover on change
const onChange = (e) => {
console.log(e.target);
data.append("image", e.target.files[0]);
console.log(data);
};
//Post Register
const Submit = async (e) => {
e.preventDefault();
await axios
.post(
"http://localhost:3000/api/book",
{
title: titleInput,
author: authorInput,
image: data,
},
{
headers: {
"auth-token": token,
},
}
)
.then((res) => {
console.log(res);
console.log(data);
})
.catch((error) => {
// handle error
console.log(error);
});
setAuthor("");
setTitle("");
};
Form
<form encType="multipart/form-data">
<input
type="text"
id="title"
value={titleInput}
name="title"
placeholder="title"
onChange={(e) => {
setTitle(e.target.value);
}}
/>
<input
type="text"
id="author"
value={authorInput}
name="author"
placeholder="Author"
onChange={(e) => {
setAuthor(e.target.value);
}}
/>
<input type="file" name="image" onChange={onChange} />
<button type="submit" onClick={Submit}>
Submit
</button>
</form>
Solved by changing the component code and sending data (create with Format()) to the node app.
//Post Register
const Submit = async (e) => {
e.preventDefault();
console.log(filename.name);
const data = new FormData();
data.append("author", authorInput);
data.append("title", titleInput);
data.append("image", filename);
data.append(
"imageTitle",
titleInput.split(" ").join("").toLowerCase() + ".jpg"
);
await axios
.post("http://localhost:3000/api/book", data, {
headers: {
"auth-token": token,
},
})
.then((res) => {
console.log(res);
})
.catch((error) => {
// handle error
console.log(error);
});
setAuthor("");
setTitle("");
};

Cloudinary return empty url on first try

It is strange that whenever I restart the ReactJS and click on postDetails, it always returns an empty URL, and if I click again it returns the URL path of the image. Am I missing something in this code here. many thanks in advance and greatly appreciated.
const Addpost = () => {
const [photo, setPhoto] = useState("")
const [photoURL, setPhotoURL] = useState("")
const postDetails = () => {
const data = new FormData()
data.append("file", photo)
data.append("upload_preset", "xxxxx")
data.append("cloud_name", "xxxxx")
fetch("https://api.cloudinary.com/v1_1/xxxxx/image/upload",{
method: "POST",
body: data
})
.then(res => res.json())
.then((data) => {
setPhotoURL(data.url)
})
.catch(err => {
console.log(err)
})
}
return (
<React.Fragment>
<input
type="file"
className="form-control-file"
id="photo"
name="photo"
onChange={(e) => setPhoto(e.target.files[0])}
/>
<button
type="submit"
className="btn btn-primary btn-block"
onClick={postDetails}
>
Submit
</button>
</React.Fragment>
)
}
try to do async await then (setPhotoUrl() will only be updated once the fetch get something or console.log('No data fetched!')):-
const postDetails = async() => {
const data = new FormData()
data.append("file", photo)
data.append("upload_preset", "xxxxx")
data.append("cloud_name", "xxxxx")
let res = await fetch("https://api.cloudinary.com/v1_1/xxxxx/image/upload",{
method: "POST",
body: data
})
if(!res) console.log('No data fetched!')
let data = res.json()
setPhotoURL(data.url)
}

Resources