Axios POST request doesn't work - node.js

I'm using Axios to send POST request to Node.js server but it doesn't work. Do you have any idea how to resolve it?
My code is shown below:
server.js:
app.post('/registration', (req, res) => {
console.log(req.body);
});
my class:
export default class Registration extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {}
}
handleSubmit (e) {
e.preventDefault;
axios.post('/registration', {name: document.getElementById('name') }).then(res => {
console.log(res);
})
}
render() {
return (<form className="registrationForm">
<input type="text" name="name" id="name" required="required" placeholder="name"/>
<br/>
{/*<input type="text" name="email" required="required" placeholder="email"/>
<br/>
<input type="number" name="phoneNumber" required="required" placeholder="phoneNo"/>
<br/>
<input type="password" name="password" required="required" placeholder="pass"/>
<br/> */}
<button className="registerButton" onClick={this.handleSubmit}>register</button>
</form>)
};
}

You have various problems in your code
preventDefault is method. You need to call it
I doubt you want to send DOM element to the server
You want to handle network failure using catch
Corrected handleSubmit should look like this
handleSubmit (e) {
e.preventDefault(); // NB
const data = {name: document.getElementById('name').value /* NB */ };
axios.post('/registration', data).then(res => {
console.log(res);
}).catch(console.error) // now you could see what the actual problem is
}
Also it is generally not adviced to use DOM lookup methods in your React up. You should better keep a ref to the input.
<input ... ref={input => this.name = input}/>
const data = {name: this.name.value };

The problem was for just a single line that I didn't write in my server side application.
The only thing to check is to put the following line after requiring the body-parser in your file.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

Related

Express function sending multiple times

My react js file is currently like this
export default function Blog() {
const [title, setTitle] = useState('');
const [blog, setBlog] = useState('');
const sumbitBlog = () => {
axios.post('http://localhost:3001/api/insert', {
title: title,
blog: blog
});
}
return (
<div className='container'>
<div className='row'>
<form className='col-lg-12 form-group'>
<div className="form-group">
<label for="formGroupExampleInput">Title</label>
<input type="text" className="form-control"placeholder="Title" name="title" onChange={(e)=>{
setTitle(e);
}}/>
</div>
<div className="form-group">
<label for="formGroupExampleInput2">Body</label>
<input type="text" className="form-control" placeholder="Body" name="blog" onChange={(e) =>{
setBlog(e);
}}/>
</div>
<button className='btn-primary' type="submit"onClick={sumbitBlog()}>Submit</button>
</form>
</div>
</div>
);
}
And my nodejs back end code :
app.post('/api/insert', (req, res) =>{
const title = req.body.title;
const blog = req.body.blog;
const sql = `INSERT INTO posts (title, body) VALUES ("this","works")`;
db.query(sql,[title, blog], (err, result)=>{
if(err) throw err;
console.log(title);
console.log(blog)
});
});
even though it looks right, it keep sending multiple requests
I have I don't know what is happening, I tried using different ways of doing it looking from the internet, but only this way it inserts to the database. any other way it wont even try connecting to it.
the database
Try to pass a reference to the function instead of firing it every time you render it.
So:
onClick={sumbitBlog}
instead of:
onClick={sumbitBlog()}
Your backend function does not send a response back to the client, because it lacks a res.json() function call or similar. If you insert a statement
res.json(result);
after the two console.log statements, the client will receive a JSON response, which you must then use to somehow update the client so that the user can read that the insertion was successful. The following code simply alerts the user and displays the JSON, but you probably want something more elegant.
const sumbitBlog = async () => {
var response = await axios.post('http://localhost:3001/api/insert', {
title: title,
blog: blog
});
alert(JSON.stringify(response.data));
}

File upload (with other inputs and textarea) using Angular 13 and Node Js

I am trying to upload files to server using Angular and Node, using multer.
I have Todo Model as :
export class TodoModel {
todo_id !:number;
todo_title !:string;
todo_description !:string;
todo_status !:number;
todo_deleted_flag !:boolean;
todo_image !:Object;
}
todo.component.ts
title:string;
desc:string;
selected_image:File = null;
fileUploadListener(event){
//console.log(event)
//console.log(event.target.files[0])
this.selected_image = <File>event.target.files[0]
console.log(this.selected_image)
}
onSubmit(form:NgForm){
const fd = new FormData()
if(this.selected_image) {
fd.append('todo_image',this.selected_image,this.selected_image.name)
}
console.log(fd);
const todo_model : TodoModel = {
todo_id: null,
todo_title:this.title,
todo_description:this.desc,
todo_status:1,
todo_deleted_flag:false,
todo_image:null
}
console.log(fd);
this.todoAdd.emit(todoadded);
this.todoAdd_DB.emit(todo_model);
this.addTodo_DB(todo_model, fd)
form.resetForm();
}
addTodo_DB(todo_db: TodoModel, fileUpload:Object){
//const todo_db
return this.http.post<{message:any}>('http://localhost:3000/api/todos/post_all_todos_db', todo_db,fileUpload).subscribe(data => {
console.log(data.message);
console.log(todo_db);
})
}
todo.component.html
<div class="col-md-12">
<form (ngSubmit)="onSubmit(todoForm)" #todoForm="ngForm">
<div class="mb-3">
<label for="todo_title" class="form-label">Title</label>
<input type="text" class="form-control" id="todo_title" [(ngModel)]="title" name="title">
</div>
<div class="mb-3">
<label for="label" class="form-label">Description</label>
<textarea class="form-control" id="todo_description" [(ngModel)]="desc" name="desc"></textarea>
</div>
<div class="mb-3">
<label for="todo_image" class="form-label">Image</label>
<input type="file" class="form-control" id='todo_image' (change)="fileUploadListener($event)">
</div>
<button type="submit" class="btn btn-success">Add To Do</button>
</form>
</div>
</div>
And on Server Side, using Node Js and PgSQL :-
app.post('/api/todos/post_all_todos_db',upload_using_multer.single('todo_images') , (req, res, next) => {
// const todo_post = req.body;
const files = req.file;
console.log(files) // - ----------> This does NOT work
console.log(req.body) //------> this works
//PGSQL insert query here
res.status(201).json({
message:"Post Added Successfully"
})
})
While doing console.log() in Angular side, I am getting the form data, but, on Node Js side, I get it as null.
Almost every tutorial I see, uses only one file upload , and that too, try to submit the form using the Form's action. I dont want to do that, so I tried doing this.
I
i once had the same issue and solved it with formdata, my example uploads multiple files. here is an example:
Node.JS
const serverRoutes = (function () {
const express = require('express');
const router = express.Router();
const multer = require('multer');
const upload = multer();
router.post('/myresource', upload.any(), (req, res) => {
console.log(req.files);
});
return router;
});
on angular
export class DataService {
constructor(private http: HttpClient) { }
sendMyFiles(file): Observable<MyResponse> {
const formData = new FormData();
formData.append("file", file);
return this.http.post<MyResponse>(
`${environment.backendAPI}myresource`,
formData
);
}
}

How to pass data from React form to Node code?

I was building a weather app using OpenWeather API. The API was fetched in Node, then data was passed to React front end, code as follows:
Node index.js
const express = require('express');
const cors = require('cors');
const app = express();
const axios = require('axios');
const dotenv = require('dotenv');
dotenv.config();
const url = `http://api.openweathermap.org/data/2.5/weather?q=london,uk&APPID=${process.env.REACT_APP_WEATHER_API_KEY}`;
app.use(cors());
app.get('/', (req, res) => {
res.send('go to /weather to see weather')
});
app.get('/weather', (req, res) => {
axios.get(url)
.then(response => {res.json(response.data)})
.catch(error => {
console.log(error);
});
})
let port = process.env.PORT || 4000;
app.listen(port, () => {
console.log(`App running on port ${port} `);
});
The weather data can then be viewed in http://localhost:4000/weather. Then React is used to display the data. Assume there is a simple React component to accept weather input and update state:
React WeatherForm.js
import React from 'react';
class WeatherForm extends React.Component {
constructor(props) {
super(props);
this.state = {
country: '',
city: ''
}
}
updateLocation(e) {
this.setState({
country: e.target.value,
city: e.target.value
});
}
render() {
return (
<form>
<div className="field">
<label className="label">Country</label>
<div className="control">
<input
className="input"
type="text"
placeholder="Type country name here"
onChange={e => this.updateLocation(e)} />
</div>
</div>
<div className="field">
<label className="label">City</label>
<div className="control">
<input
className="input"
type="text"
placeholder="Type city name here"
onChange={e => this.updateLocation(e)} />
</div>
</div>
<div className="field">
<div className="control">
<input
type='submit'
value='Search' />
</div>
</div>
</form>
)
}
}
export default WeatherForm
Question: How can I pass the country and city user input from the React app form to the country and city in the url variable in this line in the Node code?
const url = `http://api.openweathermap.org/data/2.5/weather?q=city,country&APPID=${process.env.REACT_APP_WEATHER_API_KEY}`
UPDATE I have updated the WeatherForm component as follows:
import React from 'react';
import Axios from 'axios';
class WeatherForm extends React.Component {
constructor(props) {
super(props);
this.state = {
country: '',
city: ''
}
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const url = 'http://localhost:4000/weather';
const location = {
country: this.state.country,
city: this.state.city
}
Axios.post(url, location).then((res) => {
// what should I do here?
}).catch((e) => {
console.log(e);
})
}
updateLocation(e) {
this.setState({
country: e.target.value,
city: e.target.value
});
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<p className="title">Weather</p>
<p className="subtitle">Check weather by city and country</p>
<div className="field">
<label className="label">Country</label>
<div className="control">
<input
className="input"
type="text"
placeholder="Type country name here"
onChange={e => this.updateLocation(e)} />
</div>
</div>
<div className="field">
<label className="label">City</label>
<div className="control">
<input
className="input"
type="text"
placeholder="Type city name here"
onChange={e => this.updateLocation(e)} />
</div>
</div>
<div className="field">
<div className="control">
<input
type='submit'
value='Search' />
</div>
</div>
</form>
)
}
}
export default WeatherForm
and I got error: POST http://localhost:4000/weather 404 (Not Found)
You want to use http requests to send the data to your backend. You can either use the native window.fetch API to send the data via a post request, or you can use a third-party library (I recommend axios).
The recommended way to send a post request on form submit in react is to store the field data in state (use the onChange prop on the input fields to update the state whenever the input value changes), and then use a handler function that gets fired when the submit button is clicked (use the onClick prop for your button element).
The handler function should get the current state (the form input field data) and pass it into the post request as the body.
When your express API receives the request, it can parse the data, and then fire off it's own API request to the openWeather API with that data as the url parameters.
UPDATE:
Updating due to updated question.
You don't have a post route defined in your express API. Therefore it won't accept post requests at the /weather route. What you need to do is write a handler that accepts post requests:
app.post('/weather', (req, res, next) => {
let { country, city } = req.body.data;
// here you send a post request to the weather API url
// to retrieve the results, then send them back
// to your react app to display them
}

Node Express upload file with additional data

I am new to Node JS want to create Rest API for Upload Image and facing this issue.
I want to create a post method with multiple files and additional data from inputs. This is my code:
index.js :
app.post('/upload-photos', upload.array('photos'), function (req, res) {
const uploadInfo = req.files.map(file => {
return {
sourceName: file.originalname,
newName: file.filename
};
});
res.send(uploadInfo);
});
My issue is I want to add some form data like (name, address, phone), has anyone else experienced this, please help me.
Thanks.
When using multer additional fields can be accessed through req.body.
app.post('/upload-photos', upload.array('photos'), function (req, res) {
const { name, address, phone } = req.body;
const uploadInfo = req.files.map(file => {
return {
sourceName: file.originalname,
newName: file.filename
};
});
res.send(uploadInfo);
});
In your form:
<form action="/upload-photos" method="post" enctype="multipart/form-data">
<input type="file" name="photos" multiple />
<input type="text" name="name" />
<input type="text" name="address" />
<input type="text" name="phone" />
</form>

Redirect React Component when submit form express

I'm trying to redirect to a React Component when submit the form with express. This is my code:
Express.js
app.use(bodyParser.urlencoded({extended: true}))
app.use(express.static(publicPath));
app.get('*', (req, res) => {
res.sendFile(path.join(publicPath, 'index.html'))
})
app.post('/charge', (req, res) => {
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)
stripe.charges.create({
amount: req.body.totalAmount * 100,
currency: 'eur',
source: req.body.stripeToken,
description: "Example charge",
receipt_email: req.body.receiptEmail
}).then((charge) => {
console.log(req.body)
}).catch((err) => {
console.log(err)
})
CheckoutForm.js
handleSubmit = (e) => {
e.preventDefault()
this.props.stripe.createToken({ name: this.state.name }).then(({ token }) => {
console.log(token)
this.stripeTokenHandler(token)
})
}
stripeTokenHandler = (token) => {
const form = document.getElementById('form')
const hiddenInput = document.createElement('input')
hiddenInput.setAttribute('type', 'hidden')
hiddenInput.setAttribute('name', 'stripeToken')
hiddenInput.setAttribute('value', token.id)
form.appendChild(hiddenInput)
form.submit()
}
render() {
return (
<div className="payment-container">
<form id="form" className="checkout-form" onSubmit={this.onSubmit}>
<label>
Card Number
<CardNumberElement
onChange={this.onChange}
style={{ base: { color: 'white' } }}
/>
</label>
<label>
Titular Name
<input
type="text"
value={this.state.name}
onChange={this.handleText}
className="input-text"
placeholder="Full Name"
/>
</label>
<label>
Expiration Date
<CardExpiryElement style={{base: {color: 'white'}}} />
</label>
<label>
CVC
<CardCVCElement style={{base: {color: 'white'}}} />
</label>
<label>
Email
<input
type="text"
value={this.state.email}
onChange={this.handleEmail}
className="input-text"
name="receiptEmail"
placeholder="Email"
/>
</label>
<button className="btn-buy">Pay now</button>
</form>
</div>
)}
}
The form submitted correctly and register the payment. When I submitted now gets the request body. What's the way to redirect a component with the request form?
If what you're looking for is your component to redirect once you hit the "Pay Now" button then I suggest you change your <button> to a <Link> component using React Router.
It would look like this
<Link to='/charge' className='btn-buy' onClick={this.formSubmit}>Pay Now</Link>
Then just remove the this.formSubmit from the form itself since its now on the button. It will redirect and submit.
If you want to WAIT to redirect after you get a reply, then in your formSubmit function, after you get a reply back from the server you can use this.props.history.push('/charge') in then then portion of your form submitter.
Keep in mind you will need to import { Link } from 'react-router-dom' for this.
Hope it helps!
Another way you could handle this is by using a Redirect component from React Router. Something like this:
// in the route, if the post was successful
res.json({data: 'whatever data you want', success: true})
// and if it was unsuccessful
res.json({success: false})
And here's a really stripped down react component to go with it:
class FormComponent extends Component {
constructor() {
super();
this.state = {
// inputs or whatever
success: true,
}
this.handleFormSubmit = this.handleFormSubmit.bind(this)
}
handleFormSubmit(e) {
e.preventDefault();
fetch('send the data', { with: 'some options' })
.then(res => res.json())
.then(jsonRes => {
const { success } = jsonRes;
this.setState({ success });
})
.catch(err => console.log(err))
}
// assorted other stuff to handle inputs or whatever
render() {
return (
<div>
<form onSubmit={this.handleFormSubmit}>
{/* inputs or whatever */}
</form>
{this.state.success && <Redirect push to='/some-other-url' />}
</div>
)
}
}
If this.state.success evaluates to true, the redirect will render; otherwise, it won't at all.
This allows you to make sure the request was successful before redirecting to another page. It also lets you give the user an error message, do something with whatever the response is, etc etc. Maybe you'd need to move the state and so on further up your component tree so more components have access to the response data, if that's something they need.

Resources