cant display image to card component on reactjs from backend nodejs - javascript

i trying to display the uploaded image from the backend (the backend using nodejs, sequlize) and i try to display it to card component (im using reactjs for the frontend) on the backend i made the image entered and saved to the folder name public/img, when im triying to upload it using postman, the image was successfully enterd into the file, here the result
enter image description here
but when i try to display the image on the frontend, the image doesnt appear, and here the error
enter image description here
the error is
GET http://localhost:3000/img/92c4c0be36fa5f1419f938f509df5472.png 404 (Not Found)
here the code of displaying data
import React, {Component} from 'react';
import {Card, CardGroup} from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import jwt_decode from 'jwt-decode';
class ProdukList extends Component{
constructor(props){
super(props);
this.state = {
items:[],
isLoaded: false
}
}
componentDidMount(){
const token = localStorage.getItem('usertoken')
const decoded = jwt_decode(token)
this.setState({
id_user: decoded.id_user,
})
console.log(decoded.id_user)
fetch(`http://localhost:4000/product/?id_user=${decoded.id_user}`)
.then(res=> res.json())
.then(
(result)=>{
this.setState({
items: result,
isLoaded: true
});
console.log(result)
},
(error) =>{
this.setState((error));
console.log(error)
}
)
}
render(){
console.log(this.state.items)
var{isLoaded,items}=this.state;
if(!isLoaded){
return<div>Loading.......</div>
}else{
return(
<div className="ProdukList">
{items && items.length > 0 ? items.map(item =>(
<CardGroup>
<Card style={{width: '18rem'}} key={item.id_produk}>
<Card.Img variant="top" src={item.image} alt="img"></Card.Img>
<Card.Body>
<Card.Title>
{item.Nama_produk}
</Card.Title>
<Card.Text>
{item.Price}<br/>
{item.Deskripsi}
</Card.Text>
<Card.Footer>
<small className="text-muted">Stock : {item.Jumlah_stock}</small>
</Card.Footer>
</Card.Body>
</Card>
</CardGroup>
)) : 'Kosong'}
{console.log(items)}
</div>
)
}
}
}
export default ProdukList;
here the model of database
const Sequelize = require("sequelize")
const db = require("../database/db")
//const {uploadDir} = require("../upload")
const multer = require("multer");
const express = require("express")
const app = express();
const path = require('path');
const crypto = require('crypto');
app.use(express.static('public/img'));
const uploadDir = '/img/';
const storage = multer.diskStorage({
destination:"./public"+uploadDir,
filename: function (req,file,cb){
crypto.pseudoRandomBytes(16, function(err,raw){
if (err) return cb (err)
cb(null, raw.toString('hex')+path.extname(file.originalname))
})
}
})
const uploadfile = multer({storage: storage, dest:uploadDir})
module.exports= uploadfile;
module.exports = db.sequelize.define(
'produks',
{
id_produk:{
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
id_user: {
type: Sequelize.INTEGER
},
Nama_toko:{
type: Sequelize.STRING
},
Nama_Produk:{
type: Sequelize.INTEGER
},
image:{
type: Sequelize.STRING,
get(){
const image = this.getDataValue('image');
return uploadDir+image;
}
},
Deskripsi:{
type: Sequelize.STRING
},
Price:{
type: Sequelize.INTEGER
},
Jumlah_stock:{
type:Sequelize.INTEGER
}
},
{
timestamps: false
}
)
here the code for post the data to database
const express=require("express")
const product = express.Router()
// const multer = require("multer");
const uploadfile = require('../upload')
const produk = require('../models/produk')
const {validationResult } = require('express-validator/check');
const { matchedData, sanitize } = require('express-validator/filter'); //sanitize form params
produk.sync().then(()=>{
console.log("produk berhasil sync")
}).catch(err=>{
console.log("produk gagal sync",err)
})
product.post('/addproduk/',[
uploadfile.single('image')
],(req,res)=>{
const errors = validationResult(req);
if(!errors.isEmpty()){
return res.status(422).json({errors: errors.mapped()})
}
const produkData = {
id_user:req.body.id_user,
Nama_toko:req.body.Nama_toko,
Nama_Produk:req.body.Nama_Produk,
image: req.file === undefined ? "": req.file.filename,
Deskripsi:req.body.Deskripsi,
Price:req.body.Price,
Jumlah_stock:req.body.Jumlah_stock
}
console.log(produkData)
if(!produkData){
res.status(400)
res.json({
error: 'Bad data'
})
}else{
produk.create(produkData)
.then(data=>{
res.send(data)
})
.catch(err=>{
res.json('error: '+err)
})
}
})

your react project has the same "/public" folder? when you launch your react project for development it launch their own "server" at port 3000, you need share the "public" folder between react and express projects

Related

PDF along with text not getting uploaded to Express from React

I want to send book details along with the pdf of the book to the database.
This is a portion of my react code.
const {user}=useSelector((state)=>state.auth)
const [file, setFile] = useState(null);
const dispatch = useDispatch()
const { values, errors, touched, handleBlur, handleChange, handleSubmit, setFieldValue } = useFormik({
initialValues: initialValues,
validationSchema: addBookSchema,
onSubmit: async(values, { resetForm }) => {
// i have used FormData only to send pdf
const formData = new FormData()
formData.append('title', values.title)
formData.append('author', values.author)
formData.append('rating', values.rating)
formData.append('numOfRatings', values.numOfRatings)
formData.append('total', values.total)
formData.append('genre', values.genre)
formData.append('file', file)
const response = await axios.post('http://localhost:5000/api/admin', formData, {
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${user.token}`,
},
});
console.log(response.data);
resetForm()
}
})
return (
// some code
<Box>
<TextField
id="pdf-input"
// label="Upload PDF"
type="file"
accept=".pdf"
// className={classes.textField}
onChange={handleFileChange}
margin="normal"
/>
</Box>
// some code
Below is my express controller which handles this input from react
// this is to start connection
const url = process.env.MONGO_URI;
const connect = mongoose.createConnection(url, { useNewUrlParser: true, useUnifiedTopology: true });
let gfs;
connect.once('open', () => {
// initialize stream
gfs = new mongoose.mongo.GridFSBucket(connect.db, {
bucketName: "uploads"
});
});
// this is the controller
const addBook = asyncHandler(upload.single('file'),async (req, res) => {
console.log(req.file.file);
console.log(req.body);
// nothing gets logged in console
res.status(200).json(req.body)
});
below is my upload middleware used in my controller
const path = require("path");
const multer = require("multer");
const { GridFsStorage } = require("multer-gridfs-storage");
const crypto = require("crypto");
const storage = new GridFsStorage({
url: process.env.MONGO_URI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads",
};
resolve(fileInfo);
});
});
},
});
const upload = multer({ storage });
module.exports = upload;
i get the following errors
//1. if i do formData.append('file', file) then i get "Warning: An unhandled error was caught from submitForm()"
//2. if i do formData.append('ebook', file) then i get "message: 'Unexpected field', stack: 'MulterError: Unexpected field\n"
//3. Nothing gets logged in my console when i console.log(req.body) in my controller.
Note: I am able to successfully send data to my database if i do not use FormData and do not take file input.
I tried various methods but i could not identify the problem. Any helps is very much appreciated. Thanks in advance.

Post requests not firing on user form

I have a react blog application with a form to submit a blog post. I have set up a server, routes, a model, and controllers for the fetch requests, and they all work when I use postman, but for some reason when I try to implement the post request on the submit button of the form, nothing gets sent to the database. Can someone help me figure out what I'm missing?
Here is the react code for the form
import React from 'react'
import fireIconImage from '../images/fireIcon.png'
import FireIcon from './FireIcon'
export default function BlogPostForm () {
const [formState, setFormState] = React.useState({ flaire: '', title: '', text: '', fireLevel: ''});
const [isHovered, setIsHovered] = React.useState();
const [isLit, setIsLit] = React.useState();
function changeFlaire(event) {
const selectedFlaire = event.target.value;
setFormState( {...formState, flaire: selectedFlaire });
}
function changeTitle(event) {
const title = event.target.value;
setFormState( {...formState, title: title });
}
function changeText(event) {
const text = event.target.value;
setFormState( {...formState, text: text });
}
function handleMouseOver(e) {
setIsHovered(e.target.id);
}
function handleMouseLeave(e) {
setIsHovered();
}
function handleFireIconClick(e) {
setIsLit(e.target.id);
}
function handleFireIconClass(fireLevel) {
const classNames = ['fireIcon']
classNames.push(`fireIcon${fireLevel}`)
if (isHovered >= fireLevel) {
classNames.push('isHeld')
}
if (isLit >= fireLevel) {
classNames.push('isLit')
}
return classNames.join(' ');
}
function submitForm(event) {
event.preventDefault();
const data = formState;
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
};
fetch('http://localhost:8000/', options);
}
const fireIconsArray = [];
for (let i = 0; i < 5; i++) {
fireIconsArray.push(
<FireIcon
onClick={handleFireIconClick}
onMouseLeave={handleMouseLeave}
onMouseOver={handleMouseOver}
className={handleFireIconClass(i+1)}
src={fireIconImage}
alt="fire icon"
id={i+1}
key={i+1}
/>
)
}
return (
<form className="postForm">
<h1 className="postFormHeader">Create a blog post!</h1>
<select
required
className="flaireSelect"
value={formState.flaire}
onChange={changeFlaire}>
<option disabled={true} value="">Choose a flaire</option>
<option value="JavaScript">JavaScript</option>
<option value="CSS">CSS</option>
<option value="HTML">HTML</option>
<option value="REACT">REACT</option>
<option value="BACKEND">BACKEND</option>
</select>
<input
value={formState.title}
onChange={changeTitle}
className="titleBox"
placeholder="title"
type="text"
id="title"
name="title"
/>
<textarea
value={formState.text}
onChange={changeText}
className="textBox"
placeholder="text"
type="text"
id="blogPost"
name="blogPost"
/>
<div className="fireIconContainer">
{fireIconsArray}
</div>
<div className="blogPostFormButtonContainer">
<button className="blogPostSubmit" type="submit" onClick={submitForm}>SUBMIT</button>
<button className="blogPostCancel" type="submit">CANCEL</button>
</div>
</form>
)
}
Here is the controller code
const asyncHandler = require('express-async-handler')
const Post = require('../models/postModel')
//Set post
//route: POST /api/posts/id
//access: Private
const setPost = asyncHandler(async (req, res) => {
if (!req.body.title) {
res.status(400)
throw new Error('Please add a title')
}
const post = await Post.create({
title: req.body.title,
flaire: req.body.flaire,
postText: req.body.text,
fireLevel: req.body.fireLevel,
})
console.log(post)
res.status(200).json(post)
})
Here are the routes
const express = require('express')
const router = express.Router()
const {getPosts, setPost, updatePost, deletePost} = require('../controllers/postController')
//this tells which url route to use when a post and get request is made
router.route('/').get(getPosts).post(setPost)
//this tells which url route to use when a delete or put request is made
router.route('/:id').delete(deletePost).put(updatePost)
here is the server
const express = require ('express')
const dotenv = require('dotenv').config()
const port = 8000 //process.env.PORT//
const connectDB = require('./config/db')
const cors = require("cors")
const {errorHandler} = require('./middleware/errorMiddleware')
//connect the database to the server//
connectDB()
//initialize the app as express object
const app = express()
app.use(cors({
origin: "http://localhost:3000"
}))
//tell the app to accept incoming and outgoing req, res as json
app.use(express.json())
app.use(express.urlencoded({extended: false})) //?//
//not sure what this does, i think its telling the route it should look for//
app.use('/', require('./routes/postRoutes'))
//make sure the app utulizes the error handler functions//
app.use(errorHandler)
//tell the app what port to listen on
app.listen(port, () => console.log(`Server started on port ${port}`))
console.log('Hello World')
and here is the model
const mongoose = require('mongoose')
const postSchema = mongoose.Schema({
title: {
type: String,
required: [true, 'Please add a title']
},
flaire: {
type: String,
required: [true, 'Please select a flaire']
},
postText: {
type: String,
required: [true, 'Please add a body to your post']
},
fireLevel: {
type: Number,
required: [true, 'Please select a fire level']
}
},
{
timestamps: true,
}
)
module.exports = mongoose.model('Post', postSchema)
You forgot to set the fireLevel in your state so the form data was incomplete GOOFY

React.Js how to redirect on form submit?

everyone.
So I have a an app, where the user can create posts, if you are the owner of this post, you can click on delete button which will show a modal and you can delete the post.
I can delete the post, but now I am trying to redirect the user back to the main page or any other page, however It doesn't work.
I tried using history.push, but it is not available, window.location.replace("/") doesn't work, and I even tried using this
const navigate = useNavigate();
and in the form submit
navigate("/");
This doesn't work at all, instead what happens is:
The DELETE request gets send
The post gets deleted from the database
The page reloads and doesn't redirect the user
The console throws fetch error
The user can see that the post is deleted only after he manualy switches pages, which I don'T want, I want the user to be automaticaly redirected once he pressed the Delete post button.
This is my package.json
"dependencies": {
"#testing-library/jest-dom": "^5.16.4",
"#testing-library/react": "^13.3.0",
"#testing-library/user-event": "^13.5.0",
"#types/jest": "^27.5.2",
"#types/node": "^16.11.41",
"#types/react": "^18.0.14",
"#types/react-dom": "^18.0.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"typescript": "^4.7.4",
"web-vitals": "^2.1.4"
},
And this is my code for form submit and delete on the Post
const Post_page = () => {
const auth = useContext(context_auth);
const { isLoading, error, sendRequest, clearError } = useHttpRequest();
const [showModal, setShowModal] = useState(false);
const userID = useParams().id;
const [title, setTitle] = useState();
const [postID, setPostId] = useState();
const [description, setDescription] = useState();
const [creator_name, setCreatorName] = useState();
const [creationTime, setCreationTime] = useState('');
const openModal = (event: any) => {
setShowModal(true);
}
const closeModal = (event: any) => {
setShowModal(false);
}
const onSubmit = async (event: any) => {
event.preventDefault();
console.log("aaaaaaaaaaaaa");
try {
const url: string = `http://localhost:8000/api/posts/${postID}`;
await sendRequest(url, 'DELETE');
window.location.replace("/");
closeModal(event);
} catch (err: any) {
console.log(err.message)
}
}
useEffect(() => {
const fetchPosts = async () => {
try {
const url: string = `http://localhost:8000/api/posts/${userID}`;
const responseData = await sendRequest(url);
console.log(responseData.post);
const data = responseData.post;
setTitle(data.title);
setDescription(data.description);
setPostId(data.id);
const timeOfCreation = new Date(data.createdAt).toDateString();
setCreationTime(timeOfCreation);
setCreatorName(data.creator_name);
} catch (err) { }}
fetchPosts();
}, [sendRequest]);
return (
<>
{isLoading &&
<h1>Loading ...</h1>
}
{ !isLoading && showModal && auth.isLoggedIn &&
<Modal title='Delete post' show={showModal} onCancel={closeModal}>
<>
<Form onSubmit={onSubmit} classname='modal_content_height_auto'>
<p className='post_description'>Do you want to delete this post ?</p>
<Button
classname='button_submit'
classname_enabled='button_submit_enabled'
classname_disabled='button_submit_disabled'
type='submit'
label='Delete'
/>
</Form>
</>
</Modal>
}
{ !isLoading &&
<here is the post stuff, hidden as its not important>
<Comments />
</div>
}
</>
)
}
export default Post_page
EDIT: Posting backend code for post DELETE
this is my route
route.delete('/:postID', deletePost)
and this is the deletePost handler
export const deletePost = async (req: Request, res: Response, next: NextFunction) => {
const postID = req.params.postID;
let post: any;
try {
post = await POST.findById(postID).populate('creator_id');
} catch (err: any) {
console.log(err.message)
const error = {
message: "Couldn't delete POST !",
code: 500
};
return next(error);
}
if(!post){
const error = {
message: "Post doesn't exist, so it could not be deleted !",
code: 404
};
return next(error);
}
try{
await post.remove();
post.creator.posts.pull(post);
await post.creator.save();
}catch(err){
const error = {
message: "Couldn't delete POST from DATABASE!",
code: 500
};
return next(error);
}
res.status(200).json({message: "Post deleted !"});
}
EDIT: ADDED SCHEMA FOR POST AND USER
This is my Schema for Post which is also connected to User Schema
import mongoose from "mongoose";
const Schema = mongoose.Schema;
const post_Schema = new Schema({
title: { type: String, required: true, },
description: { type: String, required: true, },
imageURL: { type: String },
creator_id: { type: mongoose.Types.ObjectId, required: true, ref: 'User' }, //relation bewtean post and user
creator_name: { type: String, required: true, ref: 'User' }, //relation bewtean post and user
},
{ timestamps: true }
);
export const POST: mongoose.Model<any> = mongoose.model("Post", post_Schema);
and this is my User Schema
import mongoose from "mongoose";
import mongooseUniqueValidator from "mongoose-unique-validator";
const Schema = mongoose.Schema;
const validator = mongooseUniqueValidator;
const user_Schema = new Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true, minlength: 3 },
user_image: { type: String },
posts: [{ type: mongoose.Types.ObjectId, required: true, ref: 'Post' }], //relation bewtean post and user
},{ timestamps: true }
);
user_Schema.plugin(validator);
export const USER: mongoose.Model<any> = mongoose.model("User", user_Schema);
You have to useNavigate only, since you are using react router v6
const Post_page = () => {
const auth = useContext(context_auth);
const navigate=useNavigate();
const { isLoading, error, sendRequest, clearError } = useHttpRequest();
const [showModal, setShowModal] = useState(false);
const userID = useParams().id;
const [title, setTitle] = useState();
const [postID, setPostId] = useState();
const [description, setDescription] = useState();
const [creator_name, setCreatorName] = useState();
const [creationTime, setCreationTime] = useState('');
const openModal = () => {
setShowModal(true);
}
const closeModal = () => {
setShowModal(false);
}
const onSubmit = async (event: any) => {
event.preventDefault();
console.log("aaaaaaaaaaaaa");
try {
const url: string = `http://localhost:8000/api/posts/${postID}`;
await sendRequest(url, 'DELETE');
//window.location.replace("/");
navigate("/");
closeModal();
} catch (err: any) {
console.log(err.message)
}
}
useEffect(() => {
const fetchPosts = async () => {
try {
const url: string = `http://localhost:8000/api/posts/${userID}`;
const responseData = await sendRequest(url);
console.log(responseData.post);
const data = responseData.post;
setTitle(data.title);
setDescription(data.description);
setPostId(data.id);
const timeOfCreation = new Date(data.createdAt).toDateString();
setCreationTime(timeOfCreation);
setCreatorName(data.creator_name);
} catch (err) { }}
fetchPosts();
}, [sendRequest]);
return (
<>
{isLoading &&
<h1>Loading ...</h1>
}
{ !isLoading && showModal && auth.isLoggedIn &&
<Modal title='Delete post' show={showModal} onCancel={closeModal}>
<>
<Form onSubmit={onSubmit} classname='modal_content_height_auto'>
<p className='post_description'>Do you want to delete this post ?</p>
<Button
classname='button_submit'
classname_enabled='button_submit_enabled'
classname_disabled='button_submit_disabled'
type='submit'
label='Delete'
/>
</Form>
</>
</Modal>
}
{ !isLoading &&
<here is the post stuff, hidden as its not important>
<Comments />
</div>
}
</>
)
}
export default Post_page
If you are getting a fetch error from the delete request, that means neither of window.location.replace or closeModal functions are getting invoked because catch block is executed right after the error. Make sure that you are getting the right response from that API call.
From what you posted, the reason you don't redirect upon post deletion is because the backend prevents it from happening.
to redirect the user after he has deleted the post, if you are using React-router-dom version 6, you need to use useNavigate(), because useHistory and have been replaced by useNavigate(), so this is how you would redirect the user if he deletes something.
const navigate = useNavigate();
const onSubmit = async (event: any) => {
event.preventDefault();
try {
const url: string = `http://localhost:8000/api/posts/${postID}`;
await sendRequest(url, 'DELETE');
closeModal(event);
navigate(`/`);
} catch (err: any) {}
}
The reason your post doesn'T redirect is because, when you send the DELETE request the backend sends back an error, but before the error happens the Post gets deleted from the database, and its happening in the second try..catch block. The error happens here ->
post.creator.posts.pull(post); //THIS IS WERE THE ERROR HAPPENS
The error happens because you are searching for creator in the Post Schema, but Post Schema doesn't have creator so it panics and throws an error, instead it has creator_id and creator_name, so you should replace it like this, if you are searching for user by ID
post.creator_id.posts.pull(post);
So your code on the backend should look like this (Its totaly same expect the post.creator_id.posts.pull(post)
export const deletePost = async (req: Request, res: Response, next: NextFunction) => {
const postID = req.params.postID;
let post: any;
try {
post = await POST.findById(postID).populate('creator_id');
} catch (err: any) {
console.log(err.message)
const error = {
message: "Couldn't delete POST !",
code: 500
};
return next(error);
}
if(!post){
const error = {
message: "Post doesn't exist, so it could not be deleted !",
code: 404
};
return next(error);
}
try{
await post.remove();
post.creator_id.posts.pull(post);
await post.creator_id.save();
}catch(err){
const error = {
message: "Couldn't delete POST from DATABASE!",
code: 500
};
return next(error);
}
res.status(200).json({message: "Post deleted !"});
}

Express.js 400 (Bad Request)

I have created new route "/bookroom" for my application, however, I keep getting an error:
POST http://localhost:3000/api/bookings/bookroom 400 (Bad Request)
I am not sure what is causing this error. Below I have listed the code from my frotnend and backend. I would be gratefull for any help.
Server.js
const express = require("express");
const app = express();
const dbConfig = require('./db')
app.use(express.json())
const roomsRoute = require('./routes/roomsRoute')
const usersRoute = require('./routes/usersRoute')
const bookingsRoute = require('./routes/bookingsRoute')
app.use('/api/rooms', roomsRoute)
app.use('/api/users', usersRoute)
app.use('/api/bookings', bookingsRoute)
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`App listening on port ${port}`)
});
Backend - bookingsRoute.js
const express = require('express')
const router = express.Router()
const Booking = require("../models/booking")
router.post("/bookroom", async(req, res)=>{
const {
room,
userid,
fromdate,
todate,
totalamount,
totaldays} = req.body
try{
const newbooking = new Booking({
room: room.name,
roomid: room._id,
userid,
fromdate,
todate,
totalamount,
totaldays,
transactionId: '1234'
})
const booking = await newbooking.save()
res.send('Room booked successfully')
}catch(error){
return res.status(400).json({ message: 'error' });
}
})
module.exports = router
Fronted - Bookingscreeen.js
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import Loader from '../components/Loader'
import Error from '../components/Error'
import moment from 'moment'
function Bookingscreen({ match }) {
const [loading, setloading] = useState(true)
const [error, seterror] = useState()
const [room, setroom] = useState()
const roomid = match.params.roomid
const fromdate = moment(match.params.fromdate , 'DD-MM-YYYY')
const todate = moment(match.params.todate , 'DD-MM-YYYY')
const totaldays = moment.duration(todate.diff(fromdate)).asDays() + 1
const [totalamount, settotalamount] = useState()
useEffect(() => {
try {
setloading(true)
async function gettingRoom() {
const data = (await axios.post('/api/rooms/getroombyid', { roomid: match.params.roomid })).data
setroom(data)
setloading(false)
settotalamount(data.rentperday * totaldays)
}
gettingRoom()
}
catch (error) {
seterror(true)
console.log(error)
setloading(false)
}
}, [])
async function bookRoom(){
const bookingDetails = {
room,
userid: JSON.parse(localStorage.getItem('currentUser'))._id,
fromdate,
todate,
totalamount,
totaldays
}
try{
const result = await axios.post('/api/bookings/bookroom', bookingDetails)
}catch(error){
console.log(error)
}
}
return (
<div className='m-5'>
{loading ?
(<Loader />)
: room ?
(
<div>
<div className='row justify-content-center mt-6 bx_shadow'>
<div className='col-md-5'>
<h1>{room.name}</h1>
<img src={room.imageurls[0]} classname='fullsizeimg' />
</div>
<div className='col-md-5'>
<h1>Szczegóły rezerwacji</h1>
<hr></hr>
<b>
<p>Nazwa: {room.name} </p>
<p>Od: {match.params.fromdate}</p>
<p>Do: {match.params.todate}</p>
<p>Dni: {totaldays}</p>
<p>Cena za dzień: {room.rentperday} </p>
<p>Suma: {totalamount}</p>
</b>
<div>
<button style={{ float: 'right' }} className='room_btn' onClick={bookRoom}> Zarezerwuj</button>
</div>
</div>
</div>
</div>)
: (<Error />)
}
</div>
)
}
export default Bookingscreen
Model - bookings.js
const mongoose = require("mongoose")
const bookingSchema = mongoose.Schema({
room : {
type: String, required: true
},
roomid : {
type: String, required: true
},
userid : {
type: String, required: true
},
fromdate : {
type: String, required: true
},
todate : {
type: String, required: true
},
totalamount : {
type: Number, required: true
},
totaldays : {
type: Number, required: true
},
transactionid : {
type: String, required: true
},
status: {
type: String, required: true, default : "booked"
}
},{
timestamps: true,
})
const bookingmodel = mongoose.model('bookings', bookingSchema)
module.exports = bookingmodel
Your PORT ENV Is undefined currently so Your port is 5000. But you are requesting from localhost:3000

can't upload a image to express api with Multer from react

I want to upload a image from my react app to my express API.
i made something like this in vainla js and it work ed with same endpoint but in react project doesn't work .
I created a react component like this:
import React, { useState } from "react";
import BackupIcon from "#material-ui/icons/Backup";
import url from "../url";
import Preview from "./Preview";
const AdaugaImg = props => {
const [file, setFile] = useState(null);
const [ales, setAles] = useState(false);
const [imgUrl, setImgUrl] = useState("");
const modificare = e => {
//console.log(e.target.value);
setFile(e.target.files[0]);
setAles(true);
const urlImg = URL.createObjectURL(e.target.files[0]);
//console.log(urlImg);
//reader.onloadend = e => setImgUrl(reader.result);
setImgUrl(urlImg);
};
const upload = async e => {
e.preventDefault();
setAles(false);
console.log("incarcare");
console.log(file);
try {
const data = new FormData();
data.append("img", file);
const res = await fetch(`${url}/add`, {
method: "POST",
data: data
});
console.log(await res.json());
} catch (error) {
console.log(error);
}
};
const closePreview = () => setAles(false);
const preview = ales ? (
<Preview imgUrl={imgUrl} closePreview={closePreview} />
) : null;
return (
<div className="upload">
{preview}
<form method="POST" onSubmit={upload}>
<input
type="file"
name="img"
id="poza"
style={{ width: 0.1, height: 0.1 }}
onChange={modificare}
/>
{!ales ? (
<label for="poza" className="upload-label">
<p>Selecteaza o poza</p>
</label>
) : null}
<button className="upload-btn" type="submit">
<BackupIcon />
<p>Incarca poza</p>
</button>
</form>
</div>
);
};
export default AdaugaImg;
them I wrote code. for api using multer
const router = require("express").Router();
const multer = require("multer");
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, "img-biserici/");
},
filename: function(req, file, cb) {
cb(null, file.fieldname + "_" + Date.now() + "_.jpg");
}
});
const upload = multer({
storage: storage
});
router.post("/add", upload.array("img", 1), (req, res) => {
console.log(req.files[0]);
res.json({ ok: true });
});
when I upload image in console it shows me this error:TypeError: Cannot read property '0' of undefined .what I missed?and how to fix this?
You are missing content type in headers.
const res = await fetch(`${url}/add`, {
method: "POST",
data: data,
headers: {
'Content-Type': 'multipart/form-data'
}
});

Categories