I'm developing my first full-stack project. I developed the client side and server side. You can see the code down. When I run the client (Front end side ) it is working in localhost. Then when I ran the backend side I got a 'Cannot GET' message. Any idea about this?
Index.js
const express = require("express");
const app = express();
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const authRoute = require("./routes/auth");
const userRoute = require("./routes/users");
const postRoute = require("./routes/posts");
const categoryRoute = require("./routes/categories");
const multer = require("multer");
const path = require("path");
dotenv.config();
app.use(express.json());
app.use("/images", express.static(path.join(__dirname, "/images")));
mongoose.connect(process.env.MONGO_URL).then(console.log('Connected to mongo')).catch(err=>console.log(err));
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "images");
},
filename: (req, file, cb) => {
cb(null, req.body.name);
},
});
const upload = multer({ storage: storage });
app.post("/api/upload", upload.single("file"), (req, res) => {
res.status(200).json("File has been uploaded");
});
app.use("/api/auth", authRoute);
app.use("/api/users", userRoute);
app.use("/api/posts", postRoute);
app.use("/api/categories", categoryRoute);
app.listen("3000", () => {
console.log("Backend is running.");
});
Home.jsx
import React from 'react'
import Header from '../../components/header/Header'
import Posts from '../../components/posts/Posts'
import Sidebar from '../../components/sidebar/Sidebar'
import axios from "axios";
import { useEffect, useState } from "react";
export default function Home() {
const [posts, setPosts] = useState([]);
useEffect(() => {
const fetchPosts = async () => {
const res = await axios.get("/posts");
console.log(res)
setPosts(res.data);
};
fetchPosts();
});
return (
<>
<div className="mt-8">
<Header/>
</div>
<div className="container">
<div className="row mt-5">
<div className="col-lg-4 col-md-4">
<Posts posts={posts}/>
</div>
<div className="col-lg-4 col-md-4 ms-auto">
<Sidebar/>
</div>
</div>
</div>
</>
)
}
I added proxy to package.json file. (Client side).
"proxy": "http://localhost:3000/api/",
Related
I made a MERN App and it worked perfectly on localhost. But then I hosted it to Heroku (for backend) & Netlify (for frontend). And when I make a req, it returns an empty index.html file rather than the JSON data. The heroku is configured properly. When I go to the heroku api link, it returns the data properly as JSON.
But when I go to the front end page that gets data from this Api Url and displays it, it doesn't get the data but an index.html file. This is what the req returns
This is the .js file
import React, { useState, Fragment, useEffect } from 'react';
import Blog from './Blog';
import blogImg from '../../images/blogImg.jpg';
import axios from 'axios';
import './Blog.css';
import { Link } from 'react-router-dom';
import DonateBar from '../layout/DonateBar/DonateBar';
const AllBlog = () => {
const [posts, setPosts] = useState([]);
useEffect(()=>{
const fetchPosts = async () => {
const res = await axios.get("/post");
console.log(res.data);
setPosts(res.data);
console.log(posts);
};
fetchPosts();
},[])
return (
<Fragment>
<div className='col-12 blogImgContainer'>
<img src={blogImg} />
</div>
{Array.isArray(posts) && (
<Fragment>
{
posts.forEach(post => (
<Link className='allBlogsLink' to={`/blog/${post._id}`}><Blog post={post} /></Link>
)
)
}
</Fragment>
)}
<DonateBar/>
</Fragment>
)
}
export default AllBlog
and this is my api req in the posts.js file in the server
router.get('/', async(req,res,next)=>{
try
{
let posts;
posts = await Post.find();
res.header("Access-Control-Allow-Origin", "*");
res.status(200).json(posts);
} catch (err) {
res.status(500).json(err);
}
})
and this is my index.js file in the server
const express = require('express');
const mongoose = require('mongoose');
const dotenv = require('dotenv');
const postRoute = require('./routes/posts');
const clientRoute = require('./routes/client');
const multer = require('multer');
const path = require('path');
const app = express();
dotenv.config();
app.use(express.json());
app.use("/images", express.static(path.join(__dirname, "/images")));
mongoose.connect(process.env.MONGODB_URI || "mongodb+srv://reachadmin:ZuLuMAN5386#cluster0.az4wji1.mongodb.net/ReachOutKids?retryWrites=true&w=majority", {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(console.log("Mongo DB Connected")).catch(err=>console.log(err));
const storage = multer.diskStorage({
destination:(req,file,cb) => {
cb(null,"images")
},
filename:(req,file,cb)=>{
cb(null,req.body.name);
}
});
const upload = multer({storage:storage});
app.post("/upload", upload.single("file"), (req,res)=>{
res.header("Access-Control-Allow-Origin", "*");
res.status(200).json("File Uploaded");
});
app.use("/post", postRoute);
app.use("/client", clientRoute);
app.listen(process.env.PORT || 5000, () => {
console.log("Backend is running");
});
I have tried all the solutions i could find online and searched all stackoverflow I can.
This is the GitHub Repo just in case someone can help: https://github.com/PeachyVVolf/reachoutkids
Thank you for your time
I am following a mern stack tutorial and trying to send data to api from react js form which is:
import axios from 'axios'
import { useState } from 'react'
import './share.css'
export default function Share() {
const [username, setUsername] = useState('')
const [file, setFile] = useState(null)
const handleSubmit = async(e)=>{
e.preventDefault()
const newPost = {
username: username
}
if(file){
const data = new FormData()
const fileName = file.name
data.append('name', fileName)
data.append('file', file)
newPost.pic = fileName
console.log(newPost)
try{
await axios.post('http://localhost:5000/upload', data)
}catch(err){
console.log(err)
}
}
try{
await axios.post('http://localhost:5000/post/post', newPost)
}catch(err){
console.log(err)
}
}
return (
<form className='share' onSubmit={handleSubmit}>
<div className='shareTop'>
<span>M</span>
<input className='shareInput' type='text' placeholder="What's happening?" onChange={(e)=>setUsername(e.target.value) } />
</div>
<div className='shareBottom'>
<div className='bottomIcons'>
<label htmlFor='file'>
<i class="fa-solid fa-face-meh"></i>
<input type='file' style={{display:"none"}} name='file' id='file' onChange={(e)=>setFile(e.target.files[0])} />
</label>
<i class="fa-solid fa-calendar"></i>
<i class="fa-solid fa-notes"></i>
<i class="fa-solid fa-bookmark"></i>
</div>
<button type='submit'>Tweet</button>
</div>
</form>
)
}
and my index js (serve side) file is:
const express = require('express')
const app = express()
const mongoose = require('mongoose')
const helmet = require('helmet')
const morgan = require('morgan')
const postRoute = require('./routes/posts')
const multer = require('multer')
const bodyParser = require('body-parser')
const cors = require('cors')
app.use(cors())
app.use(express.json())
app.use(morgan('common'))
app.use(helmet())
app.use(express.static('uploads'))
const storage = multer.diskStorage({
destination: function(req, file, cb){
cb(null, './uploads')
},
filename: function(req, file, cb){
cb(null, req.body.name)
}
})
const upload = multer({storage});
app.post('/upload', upload.single('file'), (req, res)=>{
})
app.use('/post/', postRoute)
mongoose.connect('mongodb://localhost:27017/twitter').then(()=>{
console.log("Connected to Database")
})
app.listen(5000, ()=>{
console.log('Listening')
})
and posts route is:
const express = require('express')
const router = express.Router()
const Post = require('../models/Post')
router.post('/post', async(req, res)=>{
const post = new Post({
username: req.body.username,
pic: req.body.pic
})
try{
const newPost = await post.save()
console.log("post has been saved")
res.status(200).json("Post has been saved")
}catch(err){
res.status(500).json(err)
}
})
router.put('/:id', async(req, res)=>{
const post =await Post.findByIdAndUpdate(req.params.id, {$set:req.body})
res.status(200).json("Account has been updated")
})
router.get('/', async (req, res)=>{
const posts = await Post.find()
res.status(200).json(posts)
})
router.delete('/', async(req, res)=>{
await Post.deleteMany()
})
module.exports = router
So the problem is that the file is being uploaded to backend but the data does not, after doing some research i realized that the second try and catch block where i am posting the content is not being called, just the first api where we upload file is being called, can someone tell me what am i doing?
this was working perfectly fine with localhost but after I deployed from Heroku it doesn't work.
please help.
Index.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const helmet = require("helmet");
const morgan = require("morgan");
const userRoute = require("./routes/users");
const authRoute = require("./routes/auth");
const postRoute = require("./routes/posts");
const multer = require("multer");
const path = require("path");
dotenv.config();
mongoose.connect(
process.env.MONGO_URL,
() => {
console.log("Connected to MongoDB");
}
);
app.use("/img", express.static(path.join(__dirname, "public/images")))
//middleware
app.use(express.json());
app.use(helmet());
app.use(morgan("common"));
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "public/images");
},
filename: (req, file, cb) => {
cb(null, req.body.name);
}
});
const upload = multer({storage});
app.post("/api/upload", upload.single("file"), (req,res)=>{
try {
return res.status(200).json("file uploaded successfully");
} catch(err){
console.log(err);
}
})
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'frontend/build')));
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, 'frontend/build', 'index.html'));
});
}
app.use("/api/auth", authRoute);
app.use("/api/users", userRoute);
app.use("/api/posts", postRoute);
//const port = parseInt(process.env.PORT) || 8800;
app.listen(process.env.PORT || 8800, () => {
console.log("backend server is running");
});
Feed.jsx
import "./feed.css";
import Share from "../share/Share";
import Post from "../post/Post";
import { useEffect, useState, useContext } from "react";
//import {Posts} from "../../dummyData";
import {axiosInstance} from "../../config";
import { AuthContext } from "../../context/AuthContext";
export default function Feed({username}) {
const [posts, setPosts] = useState([]);
const { user } = useContext(AuthContext);
//this helps you to render once when the page open. and only re-render whatever you put in[] changes, which is the dependency
useEffect(() => {
const fetchPosts = async () => {
const res = username
? await axiosInstance.get("/posts/profile/" + username)
: await axiosInstance.get("/posts/timeline/" + user._id);
console.log(user._id);
console.log(username);
console.log(res.data);
setPosts(
res.data.sort((p1,p2)=>{
return new Date(p2.createdAt) - new Date(p1.createdAt);
})
);
};
fetchPosts();
},[username, user._id])
return (
<div className="feed">
<div className="feedWrapper">
{(!username || username === user.username) && <Share/>}
{posts.map((p) => (
<Post key={p._id} post={p}/>
))}
</div>
</div>
);
}
if I do Console.log(res.data) from Feed.js, I see index.html data instead of JSON data I should be getting from "api/posts/timeline/"...
this was working perfectly fine with localhost but after I deployed from Heroku it doesn't work.
please help.
I am making a pinterest clone so I need to upload images but I cant fetch files from frontend to back end(with axios)
this is the server
I tested so many stuff but I can't understand where is the flaw. The app stores the photo and it seems that the problem happens when I want to get the data to backend but only files cuz I can fetch string from frontend
const express = require('express');
const app = express()
const mongoose = require('mongoose')
const cors = require('cors')
const Photo = require('./models/Photo')
const multer = require('multer')
//MiddleWare
app.use(cors())
app.use(express.json())
mongoose.connect('', () =>{
console.log('Connected to DB..')
})
// storage
const Storage = multer.diskStorage({
destination: 'uploads',
filename: (req, file,cb) =>{
cb(null, file.originalname)
}
})
const upload = multer({
storage: Storage,
}).single('testImage')
app.post('/add', async(req, res) =>{
console.log(req.files)
})
app.listen(3001, () =>{
console.log('Listening..')
})
And this is client side
/* eslint-disable jsx-a11y/alt-text */
/* eslint-disable react/jsx-no-comment-textnodes */
import React, { useState, useRef } from "react";
import NotificationsIcon from "#mui/icons-material/Notifications";
import AddAPhotoIcon from "#mui/icons-material/AddAPhoto";
import "./Header.css";
import axios from "axios"
const Header = ({gallery, setGallery}) => {
const [open, setOpen] = useState(false);
const [photo, setPhoto] = useState('')
const handleModel = (e) => {
setOpen(!open);
};
const handlePhoto = (e) => {
setPhoto(e.target.files[0])
}
const handleSubmit = e=>{
e.preventDefault();
setOpen(!open);
console.log(photo)
axios.post('http://localhost:3001/add',{photo: photo})
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
}
return (
<div className="header">
<div className="nav">
<img
src="https://i.pinimg.com/originals/0d/ea/4a/0dea4ad3030467e2f65cde00935ba62b.png"
className="logo"
/>
<input type="text" className="search-input" placeholder="Search" />
<NotificationsIcon color="action" fontSize="large" className="icon" />
<AddAPhotoIcon
color="action"
fontSize="large"
className="add-icon icon"
onClick={handleModel}
/>
</div>
{open ? (
<form onSubmit={handleSubmit} className="popup" encType='multipart/form-data'>
<input
type="file"
accept=".png, .jpg, .jpeg"
filename='testImage'
onChange={handlePhoto}
/>
<button >Submit</button>
</form>
) : (
""
)}
</div>
);
};
export default Header;
Server console logs undefined when I upload an image but why tho??
Multer returns you a middleware when you invoke the multer() function.
so in your case you should add the middleware to your route.
const upload = multer({
storage: Storage,
}).single('testImage');
app.post('/add', upload ,async(req, res) =>{
console.log(req.file)
})
Now your route '/add' will look for the key testImage in the multipart/form-data.
You need to pass the upload as formData
const formData = new FormData();
formData.append('files', photo); //this matches req.files
const res = await axios.post('http://localhost:3001/add', formData, {
headers: formData.getHeaders() //formData will set content-type etc
});
and update route to use middleware
app.post('/add', upload, async(req, res) => {})
So basically I'm new to react and couldn't find a single doc or resources regarding uploading an Image and input value at the same time.
One Solution is Form Data, But that isn't working as expected
The other method is Serialize, But I can't find any doc that explain the way to use in React
So, it would be really great for me and the newbies of React to know about this if you anyone could help me out.
You can try the following method you can use multer with express to handle the file data that is been uploaded.
React file
import React, { Component } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
class App extends Component {
handleFileChange = e => {
this.setState({ file: e.target.files[0] });
};
handleChange = e => {
this.setState({ text: e.target.value });
};
upload = () => {
if (this.state.file) {
let data = new FormData();
data.append("file", this.state.file);
data.set("data", this.state.text);
axios
.post("http://yourhost/file", data)
.then(response => console.log(response))
.catch(error => console.log(error));
}
};
render() {
return (
<div>
<input type="text" onChange={this.handleChange} />
<input type="file" onChange={this.handleFileChange} />
<input type="button" onClick={this.upload} value="Upload" />
</div>
);
}
}
export defaults App;
express server side
const express = require('express');
const app =express();
const path = require('path');
const cors = require('cors')();
const bodyParser = require('body-parser');
const multer = require('multer')
const port =process.env.PORT || 3000;;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended:true
}));
app.use(cors);
const storage = multer.diskStorage({
destination: __dirname +'/media/',
filename(req, file, cb) {
console.log(file);
cb(null, `${file.originalname}-${new Date()}`);
}
});
const upload = multer({ storage });
app.post('/file',upload.single('file'), function(req, res) {
console.log(req.body.data);
console.log(req.files);
});
app.listen(port,()=> console.log('Running on port: '+port));