how do i send react data to express backend? - reactjs

im building an app with express backend and react frontend but stack on hot to post data to my backnd.
this is my react frontend;
import React from 'react';
import axios from 'axios';
export default class PersonList extends React.Component {
state = {
name: '',
}
handleChange = event => {
this.setState({ name: event.target.value });
}
handleSubmit = event => {
event.preventDefault();
const user = {
name: this.state.name
};
axios.post(`http://localhost:9000/testAPI`, { user })
.then(res => {
console.log(res);
console.log(res.data);
})
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>
Person Name:
<input type="text" name="name" onChange={this.handleChange} />
</label>
<button type="submit">Add</button>
</form>
</div>
)
}
}
and this is my backend script testAPI.JS;
const express = require('express');
const axios = require('axios');
const app = express.Router();
app.get('/', function(req, res) {
axios.get('http://localhost:3000/')
.then(function (response) {
console.log(response);
});
});
module.exports=app;
this is the error message im getting;
createError.js:16 Uncaught (in promise) Error: Request failed with status code 404
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:61)
any kind assistance will be apreciated

You need to actually make your express server listen
const express = require('express')
const app = express()
const port = 3000
app.post('/testAPI', (req, res) => res.send('Hello World!'))
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
And I am unsure what to do with the axios call in the backend

Related

Getting 404 Error Response in google chrome extension in React js frontend and express backend

I am trying to create a simple form handling experiment where it will put all fetched data from database and display it to user.
I am using 2 separate projects for frontend and backend.
Frontend is in react and backend is in express js.
Here is my express.js code
const express = require("express");
const monggose = require("mongoose");
const bodyParser = require("body-parser");
const { default: mongoose } = require("mongoose");
const cors = require("cors");
const { Router } = require("express");
const app = express();
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
// ================= Connectivity ========
monggose.set("strictQuery", false);
mongoose.connect("mongodb://127.0.0.1:27017/players");
const cricketerSchema = monggose.Schema({
rank: Number,
name: String,
country: String,
dob: Date,
totalRun: Number,
});
const Cricketer = monggose.model("cricketers", cricketerSchema);
// === GET ,POST, DELETE ========
app
.route("/cricketers")
.get(function (request, response) {
Cricketer.find(function (error, foundCricketers) {
if (!error) {
response.send(foundCricketers);
} else {
response.send(error);
}
});
})
.post(function (request, response) {
const c1 = new Cricketer({
// ==== here Rank is the name of the attribute of form field
rank: request.body.Rank,
// ==== here Nank is the name of the attribute of form field
name: request.body.Name,
country: request.body.Country,
dob: request.body.DOB,
totalRun: request.body.TotalRun,
});
c1.save(function (error) {
if (!error) {
console.log("Data inserted successfully");
response.send("Data added successfully...");
} else {
console.log(error);
response.send(error);
}
});
})
.delete(function (request, response) {
Cricketer.deleteMany(function (error) {
if (!error) {
response.send("All Data Deleted");
} else {
response.send(error);
}
});
});
app.listen(3010, function () {
console.log("Server is running at http://localhost:3010");
});
and here is my frontend code.
import { useEffect, useState } from "react";
import axios from "axios";
function App() {
const [name, setName] = useState("zain");
const [rank, setRank] = useState("5");
const [country, setCountry] = useState("india");
const [dob, setDOB] = useState("2023-02-21");
const [totalrun, setRun] = useState("5000");
const [cricketers, setCricketers] = useState([]);
const baseURL = "http://localhost:3010/cricketers";
useEffect(() => {
axios.get(baseURL).then((response) => {
const x = response.data;
setCricketers(x);
});
}, []);
function handlesubmit() {
const collection1 = {
Name: name,
Country: country,
DOB: dob,
TotalRun: totalrun,
Rank: rank,
};
console.log(collection1);
useEffect(() => {
axios
.post(baseURL, collection1)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
});
}
return (
<div>
<label>Cricketer Rank:</label>
<input
type="number"
name="Rank"
value={rank}
onChange={(e) => setRank(e.target.value)}
/>
<br />
<label>Cricketer Name:</label>
<input
type="text"
name="Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<br />
<label>Cricketer Country:</label>
<input
type="text"
name="Country"
value={country}
onChange={(e) => setCountry(e.target.value)}
/>
<br />
<label>Cricketer DOB:</label>
<input
type="date"
name="DOB"
value={dob}
onChange={(e) => setDOB(e.target.value)}
/>
<br />
<label>Cricketer TotalRun:</label>
<input
type="number"
name="TotalRun"
value={totalrun}
onChange={(e) => setRun(e.target.value)}
/>
<br />
<button onClick={handlesubmit}>Submit</button>
<ul>
{cricketers.map((i) => (
<li key={i._id}>
<p>
{i.name}
{i.country}
{i.rank}
{i.dob}
{i.totalrun}
</p>
</li>
))}
</ul>
</div>
);
}
export default App;
when page is loaded, it's fetching data from database and showing it into react page component.
For post method getting following error.
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
at Object.throwInvalidHookError (react-dom.development.js:16227:9)
at useEffect (react.development.js:1634:21)
at handlesubmit (App.jsx:29:5)
My need is, I want to use functional component only and I have tried with all different solutions,
like fetch and axios.
It's not working.
When I am calling POST method from POSTMAN api it's working perfectly.
You are calling useEffect inside handleSubmit function. Hooks cannot be called inside a function. They can only be called at top level of a functional component. Refactor the handleSubmit function.
Please remove useEffect in your handleSubmit function. GET request must be put inside useEffect, but POST, PUT, PATCH,... don't. It all has to do with when the request is called. You can read further about useEffect to understand this.

Is it possible to redirect a react route from express?

I'm new to mern so wondering if this is even possible or if there are other solutions(trying to validate if a user is a user exists or not which works, then redirect to the same page which doesn't work). I know about window.location in react but I don't know how to redirect if a user already exists from react - code is below:
react register js:
import React from 'react'
import { useState } from 'react'
import { Link } from 'react-router-dom'
import Axios from "axios";
const Register = () => {
const [regUsername, setRegUsername] = useState('')
const [regPassword, setRegPassword] = useState('')
const submitUser = () => {
// testing if connected to express route
Axios({
method: "POST",
data: {
username: regUsername,
password: regPassword,
},
withCredentials: true,
url: 'http://localhost:8000/users'
})
.then(res => {
console.log(res)
// window.location = "/"
})
.catch(err => {
console.log(err)
})
}
return (
<div className="Register">
<h1>Register Page</h1><br />
<label>username</label>
<input type="text" id="username" name="username" value={regUsername} onChange={(e) => setRegUsername(e.target.value)} required></input><br></br>
<label>passowrd</label>
<input type="password" id="password" name="password" value={regPassword} onChange={(e) => setRegPassword(e.target.value)} required></input><br />
<button onClick={submitUser}>sign up</button>
<br />
<Link to="/login" type="button"> Login here</Link>
</div>
)
}
export default Register
users.js
const express = require('express')
const router = express.Router()
const userModel = require('../models/userModel')
const bcrypt = require('bcrypt')
// GET users
router.get('/', async (req, res, next) => {
try {
const users = await userModel.find()
res.json(users)
} catch (err) {
res.status(500).json({message: err})
}
})
// POST users to db
router.post('/', (req,res) =>{
// checking if user already exists
userModel.findOne({username: req.body.username}, async (err, user) =>{
// handle any errors
if (err) {
console.log(err);
}
// if username already exists in db
if(user){
res.redirect('http://localhost:3000/')
}
if(!user){
// hashing password before submitted to db
const hashedPass = await bcrypt.hash(req.body.password, 10)
// new instance of user model to be mutated
const User = new userModel({
// grabbing user register data and pushing to mongo
username: req.body.username,
password: hashedPass
})
const newUser = await User.save()
res.json(newUser)
}
})
})
module.exports = router;
By default, a fetch or AJAX call from JavaScript will not follow the redirect header sent from the server. You would have to read the header manually, but from the documentation, it seems like Axios does this for you. Have you tried making the call yet?
If you don't want a full-page, you may need to do this another way with React Router, but the idea is the same, getting the URL from the response headers and supplying that to the React Router history.replace().

How to send a form input data containing both image and text from React front-end to Express backend using Multer

When I test sending a request containing both image and text grabbbed from user, it comes through to the backend with proper data when I use Postman. Not from React front-end, though. Request does come through but req.body seems to be empty when I console.log it from backend. What am I doing wrong? I am using Multer.
//FRONT-END
import React, { useState } from 'react';
import axios from 'axios';
const ListProperty = (props) => {
const [address, setAddress] = useState('');
const [file, setFile] = useState(null);
const [filename, setFilename] = useState('Choose File');
const handleAddressChange = (evt) => {
setAddress(evt.target.value);
};
const handlePhotoSelect = (evt) => {
setFile(evt.target.files[0]);
setFilename(evt.target.files[0].name);
};
const handleSubmit = async (evt) => {
evt.preventDefault();
const formData = new FormData();
formData.append('address', address);
formData.append('upload', file);
console.log(formData);
try {
axios.post('http://localhost:3000/listproperty', {
headers: { 'Content-Type': 'multipart/form-data' },
body: formData,
});
} catch (err) {
console.log(err);
}
};
return (
<div>
<h2>Property Listing Form</h2>
<span>Provide property address and Photo</span>
<form onSubmit={handleSubmit}>
<input
type="text"
value={address}
onChange={handleAddressChange}
name={address}
placeholder="Enter address"
/>
<br />
<input type="file" onChange={handlePhotoSelect} />
<button>Click to list</button>
</form>
</div>
);
};
export default ListProperty;
//BACK-END
const express = require('express');
const PropertyModel = require('../models/propertyModel');
const router = new express.Router();
const UserModel = require('../models/userModel');
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/images');
},
filename: function (req, file, cb) {
const uniqueName = `${Math.random().toString(32).slice(2)}.jpg`;
req.image = uniqueName;
cb(null, uniqueName);
},
});
const upload = multer({ storage });
router.post(
'/listproperty',
upload.single('upload'),
async (req, res) => {
console.log('hitting Backend router');
const property = new PropertyModel({
...req.body,
owner: req.user._id,
photo: req.image,
});
await UserModel.findByIdAndUpdate(req.user._id, {
$push: { properties: property._id },
});
try {
await property.save();
res.status(200).send(property);
} catch (err) {
console.log(err);
res.status(400).send(err);
}
}
);
module.exports = router;
If you are sending form data in the body you need to use the formidable npm module
you can install it using npm i formidable
then require formidable at top of the file
var formidable = require("formidable");
router.post(
'/listproperty',
upload.single('upload'),
async (req, res) => {
var form = new formidable.IncomingForm();
form.multiples = false;
form.parse(req, async function (err, fields, files) {
/**now here you can get all files in files and fields with fields
in your case you have sent
formData.append('address', address);
formData.append('upload', file);
above two data in form
so you can get your image from files.upload
and address fields.address **/
})
})
In addition, I would suggest you use Axios for api calls
your axios request is not right. axios post request accepts data as a second argument and third argument is for options ( headers etc ),
axios.post('http://localhost:3000/listproperty', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
another thing is your request is not being triggered at all. try setting input type to submit instead of using the button to trigger onSubmit handler of the form.
<form onSubmit={handleSubmit}>
<input
type="text"
value={address}
onChange={handleAddressChange}
name={address}
placeholder="Enter address"
/>
<br />
<input type="file" onChange={handlePhotoSelect} />
<input type="submit" value="Submit" />
</form>

React form data isn't being sent to express backend

I've followed several tutorials and SO posts, but I'm having issues sending data from a React form to the backend. I've tried both fetch and axios and nothing seems to be working. I've checked the network tab and can see that the request has been sent to the correct URL and it has returned a 200 code - but nothing is being logged in the back end.
App.js
// Require modules
const express = require("express");
const mongoose = require("mongoose");
const session = require("express-session");
var cors = require('cors');
const app = express();
app.use(cors());
// Set up
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
const port = 5000;
// Mongoose
mongoose.connect("mongodb+srv://georgegilliland:94AJK6OlK5vasVOn#george-cluster-jjfzz.mongodb.net/DPFootball?retryWrites=true&w=majority", {useNewUrlParser: true}, ()=>{
console.log("DB connected")
});
// Controllers
let login = require('./controllers/login');
app.use('/api/login', function (req, res) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader("Access-Control-Allow-Headers", "*");
res.end();
});
// POST /login
app.post("/api/login", function(req, res) {
console.log(req.body)
});
app.listen(port, () => {
console.log("Server is on, baby")
})
login.js
import React, { Component } from 'react';
import axios from 'axios';
import './login.css';
class Login extends Component{
constructor(props) {
super(props)
this.state = {
email: "",
password: ""
}
}
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
handleSubmit = e => {
e.preventDefault();
const { email, password } = this.state;
const user = {
email,
password
};
axios
.post('http://localhost:5000/api/login', user)
.then(() => console.log('done'))
.catch(err => {
console.error(err);
});
};
render(){
return (
<div id="login">
<div className="background-inner-container">
{/* <p>{this.state.response}</p> --> */}
<div className="login-register-container padding-top padding-bottom padding-left padding-right">
<div className="login-register-title">Account Login</div>
<form onSubmit={this.handleSubmit}>
<input className="form-input" type="email" id="email" name="email" placeholder="Enter Email" onChange={this.onChange}/>
<input className="form-input" type="password" id="password" name="password" placeholder="Enter Password" onChange={this.onChange}/>
<button className="form-button" type="submit">Login</button>
</form>
</div>
</div>
</div>
);
}
}
export default Login
The problem is the Express middleware. An Express middleware takes three parameters: (req, res, next). Currently you are omitting the third parameter next, which is needed to forward the request to the following handlers. Also you are currently ending the response with res.end() before the POST handler function is reached.
Try this:
app.use('/api/login', function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader('Access-Control-Allow-Methods', '*');
res.setHeader("Access-Control-Allow-Headers", "*");
next();
});
I've removed the res.end() and called the next() function instead in order to proceed with the request.
EDIT
By the way, if you only want to set CORS header, there's a handy and very common Express middleware called cors, which is highly customizable and will fit your needs. You can use it like this:
const cors = require('cors')
// ...
app.use(cors())

Category List Navigation is not working in React App

Hello I'm new to react and trying to create a E commerce website. I'm facing a specific problem in my code.
As you see from the screen shot above, the navigation of my site.
Whenever I try to click on the Shoes link under Apparel-> Girls, it doesn't redirect to new page.
I don't know where I'm getting it all wrong. Can anyone please guide me on this.
Or give an insight how to proceed.
My code sanbox link:
https://codesandbox.io/s/49rnm480x
My mainCategory Js
import React, { Component } from 'react';
import axios from 'axios';
import SubMenu from './subMenu';
class Navigation extends Component {
state = {
mainCategory: []
}
componentDidMount() {
axios.get('http://localhost:3030/topCategory')
.then(res => {
console.log(res.data.express);
this.setState({
mainCategory: res.data.express.catalogGroupView
})
})
}
render() {
const { mainCategory } = this.state;
return mainCategory.map(navList => {
return (
<ul className="header">
<li key={navList.uniqueID}>
<a className="dropbtn ">{navList.name} </a>
<ul className="dropdown-content">
<SubMenu below={navList.catalogGroupView} />
</ul>
</li>
</ul>
)
})
}
}
export default Navigation;
server.js
const express = require('express');
const cors = require('cors');
const Client = require('node-rest-client').Client;//import it here
const app = express();
app.use(cors());
app.get('/PDP', (req, res) => {
var client = new Client();
// direct way
client.get("http://149.129.128.3:3737/search/resources/store/1/productview/byId/12501", (data, response) => {
res.send({ express: data });
});
});
app.get('/topCategory', (req, res) => {
var client = new Client();
// direct way
client.get("http://149.129.128.3:3737/search/resources/store/1/categoryview/#top?depthAndLimit=-1,-1,-1,-1", (data, response) => {
res.send({ express: data });
});
});
app.get('/GirlShoeCategory', (req, res) => {
var client = new Client();
// direct way
client.get("http://149.129.128.3:3737/search/resources/store/1/productview/byCategory/10015", (data, response) => {
res.send({ express: data });
});
});
const port = 3030;
app.listen(port, () => console.log(`Server running on port${port}`));
Could you please provide an example of mainCategory, as you are fetching it from your local machine and therefore it creates an error in your codesandbox.

Resources