Sending Form Data From Frontend to Backend Using Axios Using React - reactjs

I am trying to get input from the user in a form field and access the data in my backend server.js . I wanted to use this data in order to pass parameters to the Yelp Fusion API I am using. I know I can use axios for this but am unsure how to accomplish this at this time.
Here is my server.js:
const express = require('express')
const dotenv = require('dotenv').config()
const port = process.env.PORT || 5000
var axios = require('axios');
const app = express()
var cors = require('cors');
app.use(cors());
// app.get('/', (req, res) => {
// var config = {
// method: 'get',
// url: 'https://api.yelp.com/v3/businesses/search?location=Houston',
// headers: {
// 'Authorization': 'Bearer <API_KEY>
// }
// };
// axios(config)
// .then(function (response) {
// //const data = JSON.stringify(response.data);
// res.json(response.data)
// })
// .catch(function (error) {
// console.log(error);
// });
// })
app.listen(port, () => console.log(`Server started on port ${port}`))
Here is the App.js in which I need to pass the state from the input field to the backend:
import React,{useEffect,useState} from 'react';
import './App.css';
import axios from 'axios'
function App() {
const [zip,setZip] = useState("")
function handleSubmit() {
useEffect(() => {
axios.post("http://localhost:8000")
.then(res => {
console.log(res)
})
})
}
// const [results, setResults] = useState({})
// console.log(results)
// useEffect(() => {
// axios.get('http://localhost:8000').then(res => {
// console.log(res)
// })
// }, [])
return (
<div>
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
export default App;

Ok, here's what's wrong with your code:
hooks can only be placed on the first level of functional component (outside any sub-functions) and must be before any return statements.
Use effect will fire on render, in your code it looks like you wanna trigger it on event click.
I would do it this way if I were you:
function App() {
const [zip,setZip] = useState("");
const triggerAPI = useCallback(async () => {
// Use async await instead of chained promise
const res = await axios.post("http://localhost:8000", { zip: zip });
console.log(res)
}, [zip]);
const handleSubmit = useCallback((e) => {
e.preventDefault()
triggerAPI();
}, [triggerAPI])
const handleChange = useCallback((event) => {
setZip(event.target.value);
}, []);
return (
<div>
<form onSubmit={handleSubmit}>
<label>
ZIP:
<input type="text" value={zip} name="zip" onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
export default App;
changes:
I used useCallback to memoize the functions
I used async/await instead of chained promise (looks cleaner)

You use useEffect() function wrongly.
Handle the input element state properly.
To send data to the server you can use axios.post(url,data).then()
import React, { useState } from "react";
import axios from "axios";
function App() {
const [zip, setZip] = useState("");
function handleSubmit(event) {
event.preventDefault();
axios.post("http://localhost:8000", { zip: zip }).then((res) => {
console.log(res);
});
}
const handleChange = (event) => {
setZip(event.target.value);
};
return (
<div>
<form onSubmit={handleSubmit}>
<label>
ZIP:
<input type="text" value={zip} name="zip" onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
export default App;

Related

Param values are undefined during axios file upload along with text upload using FormData

I'm building a simple books management application. In a particular page, I need to upload a book's details along with a picture of the book.
I'm using formData and axios to do this. In the same request, sending the optional image as well as the text inputs.
But on reading the text fields from the body in the server side, all of them are undefined.
How can I resolve this issue ?
addBooksForm.js
import { useContext, useState } from "react";
import { useNavigate } from "react-router-dom";
import "./addbooksform.css";
import axios from "axios"
import { authContext } from "../../App";
const Addbooks = () => {
// eslint-disable-next-line
const [authDet, setAuthDet] = useContext(authContext);
const navigate = useNavigate()
const [values, setValues] = useState({
title: "",
author: "",
genreId: 1,
price: 0,
picture:null
});
const handleSubmit = async (e) => {
e.preventDefault();
let data = new FormData()
data.set("title", values.title)
data.set("author", values.author)
data.set("genreId", values.genreId)
data.set("price", values.price)
data.set("picture", values.picture)
console.log(values)
const response = await axios.post("http://localhost:5000/api/books/",data,
{
headers:{
Authorization:`Token ${authDet.accessToken}`
}
})
if (response.status === 200) {
navigate('/yourbooks');
} else {
console.log("Error occurred "+ response)
}
};
const onChange = (e) => {
setValues({ ...values, [e.target.name]: e.target.value });
};
const onFileChange = (e) => {
setValues({...values, [e.target.name] : e.target.files[0] })
}
return (
<div className="addbooks">
<form onSubmit={handleSubmit}>
<h3>Title</h3>
<input type="text" name="title" required={true} onChange={onChange} value={values.title}/>
<h3>Author</h3>
<input type="text" name="author" required={true} onChange={onChange} value={values.author}/>
<h3>Genre</h3>
<input type="number" name="genreId" required={true} onChange={onChange} value={values.genreId}/>
<h3>Price</h3>
<input type="number" name="price" required={true} onChange={onChange} value={values.price}/>
<h3>Upload picture</h3>
<input type="file" name="picture" onChange={onFileChange}/>
<button>Add</button>
</form>
</div>
);
};
export default Addbooks;
I have also tried adding content-type:multipart/form-data in the config
Server side controller:
const addBooks = (e) => {
const { title, author, price, genreId } = req.body;
// further processing
}
here, all the fields are undefined
server.js:
app.use(express.urlencoded({extended:true}))
app.use(express.json())
app.use(cors())
Any help is appreciated. thanks in advance !!

inputbox onchange event is not updating state in React JS

I'm learning React JS and trying to create a CRUD app. In a form, I could able to successfully fetch existing data and bind into forms controls. However, the onchange event of an input box does not seem to update the corresponding state. Sharing the code sample. Any input is highly appreciated.
import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import { useNavigate } from "react-router-dom";
function BookEdits() {
const navigate = useNavigate();
const [data, setData] = useState("");
const [title, setTitle] = useState("");
const params = useParams();
// Please ignore this part
const handleSubmit = (event) => {
event.preventDefault();
const requestOptions = {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: title,
description: description,
author: author,
}),
};
fetch(`https://localhost:7174/api/books/${params.id}`, requestOptions).then(
(response) => {
console.log(response);
if (!response.ok) alert("Error saving book details");
else alert("Book details is saved successfully");
navigate("/BooksList");
}
);
};
//
useEffect(() => {
fetch(`https://localhost:7174/api/Books/${params.id}`)
.then((response) => response.json())
.then(setData);
}, []);
// Does not change post onchange event
console.log(data.title);
return (
<form onSubmit={handleSubmit}>
<label>
Title:
<input type="submit" />
</form>
);
<input
type="text" value={data.title}
onChange={(e) => setTitle(e.target.value)}
/>
</label>
<input type="submit" />
</form>
);
}
export default BookEdits;
State should update post onchange event. What am I missing here? Thanks in advance.
data.title isn't the same as title. You call setTitle, which changes title, but you're logging data.title, which isn't the same attribute.

React Axios Post Always return Cannot post

Well my problem its that always that i send the login info to the backend, react return me Cannot Post /login. The problem its that i have a res.redirect to the main page but it dosent work and i dont know if its an error of Axios or the controller, because the information arrives correctly. What do you think? What issue im having?
React Login
import React, {Component} from "react";
import "./user.css"
import Api from "../Instrumentos/apiInstrumentos"
import { withRouter } from "react-router";
class User extends Component {
constructor(props){
super(props);
this.state = {
user: []
}
};
async componentDidMount(){
try{
console.log()
const id = this.props.match.params.id;
let user = await fetch(`http://localhost:5000/user/${id}`).then(response =>
response.json())
this.setState({
user: user
});
console.log(this.state.user)
}
catch(error){
console.log(error);
}
}
render(){
let user = this.state.user
return (
<section id="user-detail">
<section id="user_saved">
<article>
<figure id="user_figure">
<img src={`http://localhost:5000${user.photo}`} />
</figure>
<h3 id="bienvenido_user">Bienvenido {user.nombre}</h3>
<form className="margin-sections">
<fieldset>
<input type="text" name="" placeholder={user.nombre}
className="input-profile"></input>
</fieldset>
<fieldset>
<input type="text" name="apellido" placeholder={user.apellido}
className="input-profile"></input>
</fieldset>
<fieldset>
<input type="password" name="password" placeholder={user.password}
className="input-profile"></input>
</fieldset>
<fieldset>
<button className="button-login button-detail"
type="submit">Enviar</button>
</fieldset>
</form>
</article>
<article>
<h3 id="Instrumentos_guardados">Instrumentos Guardados</h3>
<Api />
</article>
</section>
</section>
);
}
}
useForm Hook
import {useState} from 'react';
import Axios from 'axios';
export const useForm = (initialForm, validateForm) => {
const [form, setForm] = useState(initialForm);
const [errors, setErrors] = useState({});
const [loading,] = useState(false);
const [response,] = useState(null);
const handleChange = (e) => {
const { name,value } = e.target;
setForm({
...form,
[name]: value
});
};
const handleBlur = (e) => {
handleChange(e);
setErrors(validateForm(form));
};
const handleSubmit = (e) => {
setErrors(validateForm(form));
Axios
.post('http://localhost:5000/usuarios/login', form)
.then(response => {
console.log(response)
})
.then(data => console.log(data))
.catch(error => {
console.log(error)
})
};
return {
form,
errors,
loading,
response,
handleChange,
handleBlur,
handleSubmit
};
}
Backend Controller
const main = {
acceso: async (req, res) => {
console.log(req.body)
return res.redirect("http://localhost:3000")
}
}
Backend Routes
const express = require('express');
const router = express.Router();
const path = require("path");
const fs = require("fs");
const user = require("../controllers/user");
const multer = require("multer");
// ************ Multer ************
const dest = multer.diskStorage({
destination: function (req, file, cb) {
let dir = path.resolve(__dirname,"../../public/uploads","users",
String(req.body.nombre).trim().replace(/\s+/g, ''))
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
cb(null, dir)
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now()+ path.extname(file.originalname))
}
})
const upload = multer({storage:dest});
// ************ Routes ************
router.post("/login", user.acceso)
router.post('/guardar', upload.single("file") , user.post)
module.exports = router;
/*** Entry Point ***/
Entry point Route definition
const users = require("./routes/user");
app.use("/usuarios", users);
/*** Console.log ***/
Console.log Response { email: 'juansepincha#gmail.com', password: '12345' }
From now thanks for all and have a great weekend!

Why does request.files not have the files that were sent?

I'm trying to upload a file to flask with fetch. What I do is onChange put the file in a useState hook and then onSubmit append it to FormData. After I send the file to my flask api with fetch. I put in a response to show me if the file is there or not and it keeps coming back as a blank dict.
Here is the react code.
import React, {useState} from 'react'
function App() {
const [file, setFile] = useState(null);
const fileInserted = (event) => setFile(event.target.value);
const handleSubmit = async (event) => {
event.preventDefault();
if (file) {
const data = new FormData();
data.append("file", file);
const resp = await fetch("/run", {
method: "POST",
body: data,
}).then(res => res.json())
.then(data => console.log(data.file))
.catch(error => console.error(error))
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="file"
onChange={fileInserted}
/>
<button type="submit" disabled={!file}>Submit</button>
</form>
</div>
);
}
export default App;
Here is the flask code.
#app.route("/run", methods=['GET', 'POST'])
def index():
if request.method == "POST":
if 'file' not in request.files:
return {"file": request.files}
file = request.files['file']
return {"file": file}
else:
return {"file": "this a get"}
The FormData you're populating gets recreated as an empty object on every render.
You also don't need to use an effect hook to run the fetch...
function App() {
const [file, setFile] = useState(null);
const fileInserted = (event) => setFile(event.target.value);
const handleSubmit = async (event) => {
if (file) {
const data = new FormData();
data.append("file", file);
const resp = await fetch("/run", {
method: "POST",
body: data,
});
// TODO: handle error/success
}
event.preventDefault();
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="file"
value={file}
onChange={fileInserted}
/>
<button type="submit" disabled={!file}>Submit</button>
</form>
</div>
);
}
export default App;

Api marvel response don't show react

I try to training in react and want to make a form who call the api marvel when submitted with the current input and display the name + description of the character search.
The Api call is ok but when i submit the form nothing show any advice?
import React, { Component, useEffect, useState } from 'react'
import axios from 'axios'
const SearchEngine = React.forwardRef((props, ref) => {
const [asked, setAsked] = useState([]);
const [characterInfos, setCharacterInfos] = useState([]);
const [searchTerm, setSearchTerm] = useState("");
const [loading, setLoading] = useState(true);
const [inputs, setInputs] = useState('');
const handleChange = (event) => {
setInputs(event.target.value);
console.log(inputs);
}
const getCharacters = (inputs) => {
setSearchTerm(inputs)
axios
.get(`https://gateway.marvel.com:443/v1/public/characters?name=${searchTerm}&apikey=XXX`)
.then(response => {
console.log(searchTerm)
console.log(response)
setCharacterInfos(response.data.data.results[0]);
setLoading(false);
console.log(response.data.data.results[0].name)
response.data.data.results.map((item) => {
return characterInfos.push(item.name)
})
localStorage.setItem(characterInfos, JSON.stringify(response.data))
if (!localStorage.getItem('marvelStorageDate')) {
localStorage.setItem('marvelStorageDate', Date.now());
}
})
.catch(error => {
console.log(error);
})
}
return (
<div className="search-container">
<h1>Character Infos</h1>
<form onSubmit={getCharacters}>
<input
type="text"
placeholder="Search"
value={inputs}
onChange={handleChange}
/>
<input type="submit" value="Envoyer" />
</form>
<ul>
<li>{characterInfos.name}</li>
</ul>
</div>
)
})
export default React.memo(SearchEngine)
Thanks for your help. Any to advice to show a list of all the character and make a search filter who work with minimum 3 characters?
getCharacters is fired with form submit event as param. You are assuming that is getting inputs from the state wrongly:
const getCharacters = event => {
event.preventDefault() // Prevent browser making undesired form native requests
// setSearchTerm(inputs); // Not sure what are you trying here but, again, inputs is a form submit event
axios
.get( // use searchValue as query string in the url
`https://gateway.marvel.com:443/v1/public/characters?name=${searchValue}&apikey=XXX`
)
.then(response => {
console.log(searchTerm);
console.log(response);
setCharacterInfos(response.data.data.results[0]);
setLoading(false);
console.log(response.data.data.results[0].name);
response.data.data.results.map(item => {
return characterInfos.push(item.name);
});
localStorage.setItem(characterInfos, JSON.stringify(response.data));
if (!localStorage.getItem("marvelStorageDate")) {
localStorage.setItem("marvelStorageDate", Date.now());
}
})
.catch(error => {
console.log(error);
});
};

Resources