multer/filepond upload returning undefined - javascript

i am currently trying to integrate multiple filepond components/instances into my react app, where the images are uploaded on button/form submit.
I have it more or less working with the code below, but i'm getting an undefined result when logging out the results in routes.js file, even though when I log out the state on submit in upload.js, i do get results.
I've tried logging out just req.files, it returns undefined, the method i've used below comes directly from multers documentation and this logs out - TypeError: Cannot read property '0' of undefined
Thanks
upload.js
import React, { useState } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import "./styles.css";
import { FilePond, registerPlugin } from "react-filepond";
import "filepond/dist/filepond.min.css";
// import FilePondPluginFileEncode from 'filepond-plugin-file-encode';
import FilePondPluginImageExifOrientation from "filepond-plugin-image-exif-orientation";
import FilePondPluginImagePreview from "filepond-plugin-image-preview";
import "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css";
// Register the plugins
registerPlugin(FilePondPluginImageExifOrientation, FilePondPluginImagePreview);
const API_BASE = "http://localhost:5000";
function submitForm(contentType, data, setResponse) {
axios({
url: `${API_BASE}/upload`,
method: "POST",
data: data,
headers: {
"Content-Type": contentType
}
})
.then(response => {
setResponse(response.data);
})
.catch(error => {
setResponse("error");
});
}
function App() {
const [title, setTitle] = useState("");
const [file, setFile] = useState("");
const [file3, setFile3] = useState("");
const [desc, setDesc] = useState("");
function uploadWithFormData() {
const formData = new FormData();
formData.append("title", title);
formData.append("file", file);
formData.append("file3", file3);
formData.append("desc", desc);
submitForm("multipart/form-data", formData, msg => console.log(msg));
}
return (
<div className="App">
<h2>Upload Form</h2>
<form>
<label>
File Title
<input
type="text"
vaue={title}
onChange={e => {
setTitle(e.target.value);
}}
placeholder="Give a title to your upload"
/>
</label>
<FilePond
name={file}
files={file}
allowMultiple={false}
server={null}
instantUpload={false}
onupdatefiles={setFile}
/>
<FilePond
name={file3}
files={file3}
allowMultiple={false}
server={null}
instantUpload={false}
onupdatefiles={setFile3}
/>
<label>
Description
<textarea value={desc} onChange={e => setDesc(e.target.value)} />
</label>
<input
type="button"
value="Upload as Form"
onClick={uploadWithFormData}
/>
</form>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
routes.js
router.post('/', upload.fields([{ name: 'file'}, { name: 'file3' }]), (req, res) => {
console.log(req.files['file'][0]);
console.log(req.files['file3'][0]);
var movieData = {
desc: req.body.desc,
title: req.body.title,
imgCollection: req.files['file'],
poster: req.files['file3']
};
Movie.create(movieData)
.then(movie => res.json({ msg: 'Movie added successfully' }))
.catch(err => res.status(400).json({ error: 'Unable to add this movie' }));
});
image of console log
console log upload.js

What you're loggin is the FilePond file item, it's not a File object. The file item has a file property that contains the actual file object, if the array you logged is what you're posting to the server you need to map it so it contains file objects instead of FilePond file items.

You should not pass any Content-type in headers.
Get file property from the files while appending like below,
formData.append("file", files.file);

Related

Unable to post form data using Reactjs

I am working with Reactjs and i am using nextjs,Right now i am trying to Post Form data But Unable to get any response(even anything in console.log),I tried with following code in index.js but nothing works,Thank you in advance
import { NextPage } from "next";
import Head from "next/head";
import Image from "next/image";
import { useEffect, useState } from "react";
import styles from "../styles/Home.module.css";
import Link from 'next/link'
import Script from 'next/script'
import ReactDOM from 'react-dom';
import axios from "axios";
//const Home: NextPage = () => {
const Home = () => {
const [state, setState] = useState({
name: "",
job: ""
});
const handleChange = (e) => {
console.log('Om Success')
const value = e.target.value;
setState({
...state,
[e.target.name]: value
});
};
const handleSubmit = (e) => {
e.preventDefault();
console.log("Om Success");
const userData = {
name: state.name,
job: state.job
};
axios.post("https://xxxxxxx.com/api/users", userData).then((response) => {
console.log(response.status);
console.log(response.data);
});
};
return (
<>
<form onSubmit={handleSubmit}>
<label htmlFor="name">
Name
<input
type="text"
name="name"
value={state.name}
onChange={handleChange}
/>
</label>
<label htmlFor="job">
Job
<input
type="text"
name="job"
value={state.job}
onChange={handleChange}
/>
</label>
<button type="submit">Register</button>
</form>
</>
);
};
export default Home;
you can post axios data by using FormData() like:
const formData= new FormData();
And then add the fields to the form you want to send:
formData.append('name', state.name);
formData.append('job', state.job);
axios({
method: "post",
url: "your url",
data: formData,
}).then((response) => {
console.log(response.status);
console.log(response.data);
});

React.js: Component updates only after refreshing the page [Post request]

Hi guys still new to react, working on a small react app supposed to display pictures of hamsters.
Inside of the AddHamster component, I have a Post request that seems to be working fine; " Object are passed into Database! "
My issue is that the object only get's displayed after refreshing the page. I
need the hamster object to be displayed on the page directly after pressing the Add Button, connected to the form.
Any clue on this?
import React, {useState} from "react";
import HamsterCard from './HamsterCard'
import './AddHamster.css';
const AddHamster = () => {
const [name, setname ] = useState('')
const [age, setage ] = useState('')
const [favFood, setfavFood ] = useState('')
const [imgName, setImgName ] = useState('')
const [hamsterItems, setHamsterItems] = useState([])
async function handleAddHamster(){
const newHamster = {
name: name,
age: Number(age),
favFood: favFood,
imgName: imgName
}
console.log(newHamster, 'newHamster')
const response = await fetch('/hamsters ', {method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(newHamster)
})
const data = await response.json()
console.log(data, "this is a data response");
if (response.status === 200){
setHamsterItems([...hamsterItems,name, age, favFood, imgName])
setname('')
setage('')
setfavFood('')
setImgName('')
}
}
return(
<div className="add-todo-wrapper">
<form onSubmit={(e) => e.preventDefault()}>
<label>name
<input type="text"
name="id"
value={name}
onChange={e => setname(e.target.value)} />
</label>
<label>age
<input type="text"
name="id"
value={age}
onChange={e => setage(e.target.value)} />
</label>
<label>favFood
<input type="text"
name="id"
value={favFood}
onChange={e => setfavFood(e.target.value)} />
</label>
<label>Image
<input type="text"
name="id"
value={imgName}
onChange={e => setImgName(e.target.value)} />
</label>
<div className="message">{hamsterItems ? <p>{[...hamsterItems]}</p> : null}</div>
</form>
<button onClick={() => handleAddHamster()}>ADD</button>
<HamsterCard />
</div>
)
}
export default AddHamster;
import React, {useState, useEffect} from "react";
import './HamsterCard.css';
const HamsterCard = () => {
const [hamsters, setHamsters] = useState([])
useEffect(() => {
async function get(){
const response = await fetch('/hamsters', {method: 'GET',})
const data = await response.json()
setHamsters(data)
console.log(data)
}
get()
}, [] );
return (
<div className="container">
<div className="hamster-card">
{hamsters.map((hamster) => (
<Hamster hamster={hamster}
key={hamster.id} />
))
}
</div>
</div>
)
}
export default HamsterCard;
import React, {useState} from "react";
const Hamster = ({name, age, favFood, hamster}) => {
const [hamsterDeleted, setHamsterDeleted] = useState(false)
async function deleteHamster(id) {
const response = await fetch(`/hamsters/${id}`, { method: "DELETE" });
setHamsterDeleted(true)
}
return (
hamsterDeleted ? null : (
<div>
<button onClick={() => deleteHamster(hamster.id)}>Delete</button>
<h2>{hamster.name}</h2>
<p>Ã…lder:{hamster.age}</p>
<p>Favorit mat:{hamster.favFood}</p>
<img src={'./img/' + hamster.imgName} alt="hamster"/>
</div>
))
}
export default Hamster;
After changing code
setHamsterItems([...hamsterItems,name, age, favFood, imgName])
to
setHamsterItems([...hamsterItems, newHamster])
I get this error message:
In the AddHamster component when you update hamsterItems it renders the whole component but in Hamstercard you are using useEffect to fetch the latest hamsters from the database
which runs only the first time the HamsterCard component mounts to re-render the HamsterCard you have to add some dependency in useEffect of HamsterCard so this will re-render the HamesterCard every time you click add button.
for which you can send hamsterItems as props to HamsterCard and pass that to useEffect dependency array.
<HamsterCard hamsterItems={hamsterItems}/>
function HamsterCard({ hamsterItems }) {
useEffect(() => {
async function get(){
const response = await fetch('/hamsters', {method: 'GET',})
const data = await response.json()
setHamsters(data)
console.log(data)
}
get()
}, [hamsterItems] );
It's now working.. problem that Is was this line:
<div className="message">{hamsterItems ? <p>{[...hamsterItems]}</p> : null}</div>
Was trying to render an object directly into the jsx..

Upload profile photo to strapi collection

I have a problem uploading a file that is a picture for a user profile in my user collection in strapi.
This is my photo form in react
import React, {useState} from 'react';
import {Form, Button} from "semantic-ui-react"
import {useFormik} from "formik";
import * as Yup from "yup";
import {toast} from "react-toastify";
import {updatePhotoApi} from "../../../api/user";
export default function ChangeNameForm(props){
const {user, logout,setReloadUser} = props;
const [loading, setLoading] = useState(false);
const formik = useFormik({
initialValues: initialValues(user.photo),
validationSchema: Yup.object(validationSchema()),
onSubmit: async (formData) => {
console.log(formData);
setLoading(true);
const response = await updatePhotoApi(user.id, formData,logout);
console.log(response);
if(!response) {
toast.error("Error al actualizar foto ")
}else{
setReloadUser(true);
toast.success("Foto actualizada");
}
setLoading(false);
}
})
return (
<div className="change-name-form">
<h4>Cambia tu foto</h4>
<Form onSubmit={formik.handleSubmit}>
<Form.Group widths="equal">
<Form.Input
name="photo"
type="file"
placeholder="Tu nueva foto"
error={formik.errors.photo}
onChange={formik.handleChange}
value={formik.values.photo}/>
</Form.Group>
<Button className="submit" loading={loading}>Actualizar</Button>
</Form>
</div>
);
}
function initialValues(photo){
return {
photo: photo || "",
}
}
function validationSchema(){
return {
photo: Yup.string().required(true),
}
}
and there is the api call
export async function updatePhotoApi(idUser,data,logout){
try {
const url = `${BASE_PATH}/users/${idUser}`;
const params = {
method: "PUT",
headers:{
"Content-Type": "application/json"
},
body: JSON.stringify(data),
};
const result = await authFetch(url,params,logout);
console.log(result);
return result ? result : null;
} catch (error) {
console.log(error);
return null;
}
}
but im still getting error 505 internal server error, i dont know what im doing wrong, and cant find such information about to do this.
In my collection for user i have the field called photo for the a single img picture, for later show it as a avatar picture in the client

Unable to send image from frontend to cloudinary or the backend in general

I am trying to send an image from the frontend to cloudinary to be used as profile picture in my app using the code below:
import { StyledInput, StyledLabel} from '../FormInputs/styles'
import { useState } from 'react'
import { StyledButton } from '../Button/styles'
import axios from 'axios'
export function FileUploader() {
const [file, setFile] = useState(null)
const [image, setImage] = useState(null)
const [showImage, setShowImage] = useState()
function handleChange(e) {
readFile(e.target.files[0])
setFile(e.target.files[0])
console.log(e.target.files[0])
}
function readFile(file) {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = e => setImage(e.target.result)
reader.onerror = e => console.log(reader.error)
}
async function handleSubmit(e) {
e.preventDefault()
const token = localStorage.getItem('token')
const data = new FormData()
if(file) {
data.append('file', file[0], file[0].name)
}
const response = await axios({
method: 'PUT',
base: 'http://localhost:8000',
url: '/clients/clientprofile',
data,
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': `Bearer ${token}`
}
})
console.log(response)
// setShowImage(response.image)
}
return (
<div>
<form onSubmit={handleSubmit}>
<StyledLabel htmlFor="file">Elegir foto de perfil</StyledLabel>
<StyledInput
type="file"
accept="image/*"
name="file"
id="file"
onChange={handleChange}
/>
<StyledButton type="submit">Enviar Foto</StyledButton>
</form>
{image && <img src={image} alt="Profile Picture Preview" />}
</div>
)
}
When I select the image it works fine, however, when I click the "Upload Image" button, it errors out with the below error:
I am defining file by using the setFile(), however, when I console.log(file) it returns null
Since the console.log() is async, it was logging null because it was executing before the state had time to change, and the issue with the undefined was due to an error of the config in the backend.

fetch POST not working on heroku but work locally

So I tried to make a request using
import React, {useState} from 'react';
const CommentForm = (props) => {
const [inputHandler, setInputHandler] = useState();
const [nameHandler, setNameHandler] = useState();
const URL_COMMENT = `https://damp-sierra-44032.herokuapp.com/API/${props.postID}/comment`
const submitValue = async (e) => {
const data = {name: nameHandler, comment: inputHandler}
await postComment(data);
window.location.reload()
}
async function postComment(data) {
await fetch(URL_COMMENT, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
}
return (
<div>
<form>
<input type="text" name="name" placeholder="Name..." value={nameHandler} onChange={e => setNameHandler(e.target.value)} required></input>
<input type="text" name="comment"placeholder={"Write comment here..."} value={inputHandler} onChange={e => setInputHandler(e.target.value)} required></input>
<button type="submit" onClick={submitValue}>Submit</button>
</form>
</div>
)
}
export default CommentForm
to heroku from my React app and when i clicked submit button the heroku log shows
heroku log
but when I tried to request from my app that runs locally (localhost:8000) it works just fine and succesfully creates new comment.
I wonder what's wrong?

Categories