I have made an API in Node and can see the data using Postman and by hiting the endpoint in the browser. But, when I try to fetch it using React, I can't see it and am getting few errors. one of them is related to the CORS, which I tried to solve by adding a proxy in the package.json of the client folder but it's still not getting solved. Here's my code:
Error:
img
App.js
import React, { useState, useEffect } from "react";
import "./App.css";
//Pages
//components
import Navbar from "./Components/Navbar";
function App() {
let initialData = [];
const [data, setData] = useState(initialData);
const [isFetched, setIsFetched] = useState(false);
useEffect(() => {
let headers = new Headers({
"Content-Type": "application/json",
Accept: "application/json",
});
fetch(`http://localhost:4000/`, headers)
.then((res) => res.json())
.then(
(result) => {
setData(result);
setIsFetched(true)
console.log("result"+result)
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
(error) => {
console.log(error);
}
);
});
return (
<div className="container">
<Navbar data={data} isFetched={isFetched} />
</div>
);
}
export default App;
NodeJs code:
const router = require('express').Router();
router.route('/').get((req, res) => {
let displayData=[{
user:'a',
id:1
},
{
user:'b',
id:2
}
]
res.status(200).json(displayData);
res.send("<h1>Home</h1>")
})
module.exports = router
server.js:
const express = require('express');
const cors = require('cors');
const { pool } = require("./db/dbConfig")
const app = express();
const port = process.env.PORT || 4000;
const homeRouter = require("./routes/home")
//middleware
app.use("/", homeRouter);
app.use(cors());
app.use(express.json());
app.listen(port, () => {
console.log(`We are live on port: ${port}`);
});
Related
I want to view a pdf sent from my backend (nodeJS)
my route
router.route("/getPdf").post(getPdf);
I need to use "POST" req as my pdfs are saved using user id's which I need to find the pdf
my controller
exports.getPdf = async (req, res) => {
const id = req.body.id;
var pdf = fs.readFileSync(
path.join(__dirname, "..", "/submits", id + ".pdf")
);
res.contentType("application/pdf")
res.send(pdf);
};
react component
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";
const PDFPreview = () => {
const { id } = useParams();
useEffect(() => {
try {
var res = axios.post("http://localhost:3000/api/pdf/getPdf", { id });
console.log(res)
} catch (error) {
console.log(error);
}
}, []);
return ("Hi");
};
export default PDFPreview;
on Console logging my response
I am new to ReactJS and trying to find a way to connect my React front end to my Express js backend. To do this, I am just setting up a simple form that sends a POST request after I press a register button in a form.
The problem is I keep getting these error messages in the console.
These are the errors
POST http://localhost:3000/api/users 404 (Not Found)
Error: Request failed with status code 404
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.onloadend (xhr.js:66)
This is the react code
import Proj from './Proj'
import React, {Fragment, useState} from 'react'
import axios from 'axios';
export const Homepage = () => {
const [formData, setFormData] = useState({
name:'',
});
const { name } = formData;
const onChange = e =>
setFormData({...formData, [e.target.name]:e.target.value})
const onSubmit = async e => {
console.log('submitted')
e.preventDefault();
const newUser = {
name,
}
try {
const config = {
headers:{
'Content-Type':'application/json'
} }
const body = JSON.stringify(newUser)
const res = await axios.post('/api/users',body, config)
console.log(res)
} catch (err) {
console.error(err)
}
}
return (
<div className="Landing">
<Proj/>
<section>
<form onSubmit = {e=>onSubmit(e)}>
<input
type="text"
placeholder="Name"
name="name"
value = {name}
onChange = {e =>onChange(e)}
required />
<input type="submit" className="btn btn-primary" value="Register" />
<h1>Contact</h1>
</form>
</section>
</div>
)
}
export default Homepage
This App.js
import { Navbar } from './components/Navbar';
import Homepage from './components/Homepage';
import Projects from './components/Projects';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import './App.css';
function App() {
return (
<Router>
<div className="App">
<Navbar/>
</div>
<Route exact path="/" component={Homepage} />
<Switch>
<Route exact path="/Projects" component={Projects} />
</Switch>
</Router>
);
}
export default App;
This is my server side JS
const express = require ('express')
const path = require('path');
const app = express()
app.use(express.urlencoded({extended: false}));
app.use('/', require('./routes/api/users'))
// Serve static assets in production
if (process.env.NODE_ENV === 'production'){
app.use(express.static('client/build'))
app.get('*', (req,res)=>{
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
})
}
const PORT = 5000
app.listen(process.env.PORT || 5000)
and this is users.js in the api folder in routes
const express = require('express')
const router = express.Router();
router.post('/', async (req,res)=>
{
console.log('its working, and here is the data', req.body)
})
module.exports = router;
client side package.json
"proxy":"http://localhost:5000",
I would really appreciate it if someone can tell me what I am doing wrong or if there is a better way to do things.Thanks.
Instead of
app.use('/', require('./routes/api/users'))
type in
app.use('/api/users', require('./routes/api/users'))
You are posting currently to a route that does not exist.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
So, I am attempting a simple, single-page application on the MERN stack that takes notes - a note title and a note content and displays them on the same root route; the data is supposed to also be saved on the backend for later retrieval. At this time, there is no authentication. My backend seems to be working perfectly, but when I connect the front end React application to the backend MongoDB database, my GET request (using axios instance) fails.
My backend renders on localhost:5000, no problem.
But on localhost:3000, I'm seeing this error in App.jsx:
Error: Request failed with status code 404
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:62)
Here's what I have going on:
BACKEND
// server.js
import express from 'express';
import cors from 'cors';
import notes from './api/notes.route.js';
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/api/v1/notes', notes);
app.use('*', (req, res) => res.status(404).json({ error: 'not found' }));
export default app;
// notes.route.js
import express from 'express';
import NotesController from './notes.controller.js';
const router = express.Router();
router
.route('/')
.get(NotesController.apiGetNotes)
.post(NotesController.apiPostNote)
.put(NotesController.apiUpdateNote)
.delete(NotesController.apiDeleteNote);
export default router;
// notes.controller.js
import NotesDAO from '../dao/notesDAO.js';
class NotesController {
static apiGetNotes = async (req, res, next) => {
const notesPerPage = req.query.notesPerPage
? parseInt(req.query.notesPerPage)
: 20;
const page = req.query.page ? parseInt(req.query.page) : 0;
const { notesList, totalNumNotes } = await NotesDAO.getNotes({
page,
notesPerPage
});
let response = {
notesList,
page,
notesPerPage,
totalNumNotes
};
res.json(response);
};
export default NotesController;
// notesDAO.js
import mongodb from 'mongodb';
const ObjectID = mongodb.ObjectId;
let notes;
class NotesDAO {
// call this on db connection:
static injectDB = async conn => {
if (notes) return;
try {
notes = await conn.db(process.env.NOTESDB_NS).collection('notes');
} catch (e) {
console.error(`unable to establish collection handle in notesDAO: ${e}`);
}
};
static getNotes = async ({ page = 0, notesPerPage = 20 } = {}) => {
let query;
let cursor;
try {
cursor = await notes.find(query);
} catch (e) {
console.error(`unable to issue find command, ${e}`);
return { notesList: [], totalNumNotes: 0 };
}
const displayCursor = cursor.limit(notesPerPage).skip(notesPerPage * page);
try {
const notesList = await displayCursor.toArray();
const totalNumNotes = await notes.countDocuments(query);
return { notesList, totalNumNotes };
} catch (e) {
console.error(
`unable to convert cursor to array or problem counting documents, ${e}`
);
return { notesList: [], totalNumNotes: 0 };
}
};
}
export default NotesDAO;
FRONTEND
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route } from 'react-router-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<Route path="/" component={App} />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
// App.jsx
import { useState, useEffect } from 'react';
import NoteDataService from './services/note.js';
import Header from './Header';
import Footer from './Footer';
import CreateArea from './CreateArea';
import Notes from './Notes';
const App = () => {
const [notes, setNotes] = useState([]);
useEffect(() => {
retrieveNotes();
}, []);
const retrieveNotes = async () => {
await NoteDataService.getAll()
.then(response => {
console.log(response.data);
setNotes(response.data.notes);
})
.catch(e => console.log(e));
};
return (
<>
<Header />
<CreateArea clicked={addNote} />
<Notes notes={notes} clicked={deleteNote} />
<Footer />
</>
);
};
export default App;
// http-common.js
import axios from 'axios';
export default axios.create({
baseURL: 'http://localhost:5000/api/vi/notes',
headers: {
'Content-type': 'application/json'
}
});
// note.js
import http from '../http-common.js';
class NoteDataService {
getAll() {
return http.get('/');
}
}
export default new NoteDataService();
You have a typo. The backend route is /api/v1/notes, but the frontend is sending requests to /api/vi/notes
I am trying to emit a data to client via socket.io in next.js setup.But i dont get any data via it.
Below is my server.js code
const app = require('express')()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const nextApp = next({ dev })
const nextHandler = nextApp.getRequestHandler()
// socket.io server
io.on('connection', socket => {
console.log('a user is connected')
socket.broadcast.emit('now', {
message: 'Hello'
})
socket.on('disconnect', () => {
console.log('user disconnected')
})
})
nextApp.prepare().then(() => {
app.get('*', (req, res) => {
return nextHandler(req, res)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
when a user is connected it console logs a user is connected its working fine.
into my _app.js file i have included socket.io as instructed in next.js example: https://github.com/zeit/next.js/blob/canary/examples/with-socket.io/pages/_app.js
Here is my _app.js file
import App from 'next/app'
import React from 'react'
import io from 'socket.io-client'
class MyApp extends App {
static async getInitialProps ({ Component, ctx }) {
let pageProps = {}
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
state = {
socket: null
}
componentDidMount () {
// connect to WS server and listen event
const socket = io()
this.setState({ socket })
}
// close socket connection
componentWillUnmount () {
this.state.socket.close()
}
render () {
const { Component, pageProps } = this.props
return <Component {...pageProps} socket={this.state.socket} />
}
}
export default MyApp
Main problem is In index.js file.Below is that file
import { Component } from 'react'
import Link from 'next/link'
import fetch from 'isomorphic-unfetch'
class ChatOne extends Component {
// init state with the prefetched messages
state = {
message: ''
}
componentDidMount () {
this.props.socket.on('now', data => {
this.setState({
message: data.message
})
})
}
render () {
return (
<div>
{this.state.message}
</div>
)
}
}
export default ChatOne
And after launch i am getting this error.I am asking this question to about the error of this question
Your first render of <App /> won't have this.state.socket as that isn't set until it has mounted.
render () {
const { socket } = this.state;
if(!socket) {
return <div>Loading...</div>
}
const { Component, pageProps } = this.props
return <Component {...pageProps} socket={socket} />
}
I'm following this tutorial which I adapt to React Router v4.
I have these files :
auth.js
const express = require('express');
const validator = require('validator');
const router = new express.Router();
function validateLoginForm(payload) {
const errors = {};
let isFormValid = true;
let message = '';
if (!payload || typeof payload.email !== 'string' || payload.email.trim().length === 0) {
isFormValid = false;
errors.email = 'Please provide your email address.';
}
if (!payload || typeof payload.password !== 'string' || payload.password.trim().length === 0) {
isFormValid = false;
errors.password = 'Please provide your password.';
}
if (!isFormValid) {
message = 'Check the form for errors.';
}
return {
success: isFormValid,
message,
errors
};
}
router.post('/login', (req, res) => {
console.log("lol");
const validationResult = validateLoginForm(req.body);
if (!validationResult.success) {
return res.status(400).json({
success: false,
message: validationResult.message,
errors: validationResult.errors
});
}
return res.status(200).end();
});
router.get('/login', (req, res) => {
console.log(req.url);
});
router.get('/', (req, res) => {
console.log(req.url);
console.log("lmao")
});
module.exports = router;
index.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const router = new express.Router();
// tell the app to look for static files in these directories
app.use(express.static('./server/static/'));
app.use(express.static('./client/dist/'));
app.use(bodyParser.urlencoded({extended:false}));
const authRoutes = require('./server/routes/auth');
app.use('/login', authRoutes);
// start the server
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000 or http://127.0.0.1:3000');
});
Base.jsx
import React from 'react';
import PropTypes from 'prop-types';
import { Link, NavLink } from 'react-router-dom';
const Base = ({ child }) => (
<div>
<div className="top-bar">
<div className="top-bar-left">
<NavLink to="/">React App</NavLink>
</div>
<div className="top-bar-right">
<Link to="/login">Log in</Link>
</div>
</div>
{child.render()}
</div>
);
Base.propTypes = {
child: PropTypes.object.isRequired
};
export default Base;
and app.jsx
import React from 'react';
import ReactDom from 'react-dom';
import injectTapEventPlugin from 'react-tap-event-plugin';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import {BrowserRouter, Switch, Route} from 'react-router-dom';
import Base from './components/Base.jsx';
import HomePage from './components/HomePage.jsx';
import LoginPag from './components/LoginPag.jsx';
// for MaterialUI to work properly
injectTapEventPlugin();
const TestLogin = (props) => {
return (<Base child={LoginPag}/>)
};
const TestBase = (props) => {
return(<Base child={HomePage}/>)
};
ReactDom.render((<BrowserRouter><MuiThemeProvider muiTheme={getMuiTheme()}>
<div>
<Switch>
<Route exact path="/" component={TestBase}/>
</Switch>
<Route exact path="/login" component={TestLogin}/>
</div>
</MuiThemeProvider>
</BrowserRouter>), document.getElementById('react-app'));
As you can see, I did a little "workaround" to have everything rendered nicely and it works. But it only works for Client-side routing.
I can't reload pages via f5 or refresh button, nor can I send form and get it through router.post(). It automatically results in a 404 not found.
I printed req.url in router.get('*') to see where the thing goes down and it appears that everywhere I go, the server still receives the address /. I believe the matter is with the <Link to> tag..
How can I fix this and get the server "follow" the client side routing ?
I'm using latest versions of Express, React, and React-Router. Thanks in advance
EDIT : Edited to take into account the remarks made by VivekN
Change your index.js file to the below one:-
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const router = new express.Router();
// tell the app to look for static files in these directories
app.use(express.static('./server/static/'));
app.use(express.static('./client/dist/'));
app.use(bodyParser.urlencoded({extended:false}));
const authRoutes = require('./server/routes/auth');
app.use('/', authRoutes);
// start the server
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000 or http://127.0.0.1:3000');
});
The problem with your code is that you had written when a request comes to your server which has /login in its path, then that should go inside auth.js file and inside that you should check for router.post('/') method.
Either this or you change the index.js file to be
app.use('/', authRoutes);