How to send a fetch post request from react component to backend - reactjs

I want to send the fetch post request to the server from react class component. I never did fetch post. So how can I do this from that component using thunk.
class Add extends Component {
constructor(props) {
super(props);
this.state = {username: '', email:'', text:''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert (JSON.stringify(this.state))
event.preventDefault();
}
render(){
return (
<div className="addcontainer">
<div style={{display: 'flex', justifyContent: 'center'}}>
<h4>Add new task here:</h4>
</div>
<form onSubmit={this.handleSubmit}>
<div className="wrapper">
<label for="username"><b>Username</b></label>
<input type="text" value={this.state.username} onChange={e => this.setState({ username: e.target.value })} placeholder="Enter Username" name="uname" required />
<label for="email"><b>Email</b></label>
<input type="text" value={this.state.password} onChange={e => this.setState({ email: e.target.value })} placeholder="Enter Email" name="email" required />
<label for="text"><b>Text</b></label>
<input type="text" value={this.state.password} onChange={e => this.setState({ text: e.target.value })} placeholder="Enter Task" name="text" required />
<button className="login" type="submit">Add task</button>
</div>
</form>
</div>
)
}
}
I also have an example of the jquery ajax request in documentation, but it is of little help to me. Please help me to write thunk with fetch
$(document).ready(function() {
var form = new FormData();
form.append("username", "Example");
form.append("email", "example#example.com");
form.append("text", "Some text");
$.ajax({
url: 'https://uxcandy.com/~shapoval/test-task-backend/create?developer=Example',
crossDomain: true,
method: 'POST',
mimeType: "multipart/form-data",
contentType: false,
processData: false,
data: form,
dataType: "json",
success: function(data) {
console.log(data);
}
});
});
Here is thunk that works with fetch get:
const getRepos = username => async dispatch => {
try {
var url = `https://uxcandy.com/~shapoval/test-task-backend/?developer=sait&sort_field=${username}`;
const response = await fetch(url);
const responseBody = await response.json();
//console.log(responseBody.message.tasks);
dispatch(addRepos(responseBody.message.tasks));
} catch (error) {
console.error(error);
dispatch(clearRepos());
}
};

You can use second argument of fetch function to add options e.g.
fetch(url, {
method: "POST", // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, cors, *same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json",
// "Content-Type": "application/x-www-form-urlencoded",
},
redirect: "follow", // manual, *follow, error
referrer: "no-referrer", // no-referrer, *client
body: JSON.stringify(data), // body data type must match "Content-Type" header
})
For more information please refer here
other effective way to make api hit is by using axios

Related

react formik + axios post, Data returns undefined in backend

I am trying to post data with axios with a formik form but when I checked my backend, data keeps returning undefined seems like the backend isn't receiving the data at all, and browser responds with AxiosError and server response 500, Moreover I am also getting another error A component is changing a controlled input to be uncontrolled after I submitted the form
this is my signup function with formik and axios.post
function Test() {
const validate = Yup.object({
name: Yup.string()
.max(15, 'Must be 15 characters or less')
.required('Required'),
email: Yup.string()
.email('Email is invalid')
.required('Email is required'),
password: Yup.string()
.min(6, 'Password must be at least 6 charaters')
.required('Password is required')
})
return (
<Formik
initialValues={{
name: '',
email: '',
password: ''
}}
validationSchema={validate}
onSubmit={data => {
console.log(data)
let formData = new FormData();
formData.append('name', data.name)
formData.append('email', data.email)
formData.append('password', data.password)
axios({
method: 'POST',
url: 'http://localhost:5000/userdata',
data: formData
})
.then(function (res) {
console.log(res)
alert('Successfully signed up!');
})
.catch(function (res) {
console.log(res)
});
}}
>
{formik => (
<div className='fbody'>
<div className='fcontainer'>
<div className="contact-box">
<div className="right">
<h1 className="my-4 font-weight-bold .display-4">Sign Up</h1>
<Form>
<TextField className="field" label="First Name" name="name" type="text" />
<TextField className="field" label="Email" name="email" type="email" />
<TextField className="field" label="password" name="password" type="password" />
<button className="btn" type="submit">Register</button>
<button className="btn" type="reset">Reset</button>
</Form>
</div>
</div>
</div>
</div>
)}
</Formik>
)
}
export default Test;
There are a few things wrong with your component.
Your inputs are not controlled. Add value and onChange props to your inputs like:
<TextField
className="field"
label="First Name"
name="name"
type="text"
value={formik.values.name}
onChange={formik.handleChange}
/>
And then update the onSubmit handler. You don't need to do new FormData()
onSubmit={data => {
console.log(data);
axios({
method: 'POST',
url: 'http://localhost:5000/userdata',
data: data
})
.then(function (res) {
console.log(res)
alert('Successfully signed up!');
})
.catch(function (res) {
console.log(res)
});
}}
you forgot to add multipart/formData header to your axios request:
axios({
method: 'POST',
url: 'http://localhost:5000/userdata',
data: formData,
headers: {'Content-Type': 'multipart/form-data'}
})

image file isnt being read by react

I am using formData to send details to my backend but somehow my image path isn't being sent.
Post photo
<div className="form-group">
<label className="btn btn-block btn-success">
<input
onChange={handleChange("photo")}
ref={inputRef}
type="file"
name="photo"
accept="image"
placeholder="choose a file"
/>
</label>
</div>
this is the form i am using
Handle change and submit button
const onSubmit = (event) => {
event.preventDefault();
setValues({...values,error:"",loading:true});
createProduct(user._id,token,JSON.stringify(values))
.then(data=>{
if(data.error){
setValues({...values,error:data.error});
}else{
setValues({...values,
name:"",
description:"",
price:"",
photo:"",
stock:"",
createdProduct:data.name,
loading:false});
}
}).then(response=>{
})
.catch(err=>console.log(err));
//
};
const handleChange = name => event => {
const value=name==="photo"?event.target.files[0]:event.target.value;
formData.append(name,value)
setValues({...values,[name]:value});
//
};
And this is the api call to backend
export const createProduct=(userId,token,product)=>{
console.log(product)
return fetch(`${API}/product/create/${userId}`,{
method: "POST",
headers:{
Accept: "application/json",
Authorization: `Bearer ${token}`
},body:product
})
.then(response=>{
return response.json();
})
.catch(err=>console.log(err));
}
The api is working fine with postman , I am using formidable in backend. Some answers from stack made the path of the file have c:\fakepath and so m too confused what to do .
Thanks for help.

How to make post request with form in React

After i filled the inputs and submitted the form, I want to make a POST request with React. When i use fetch outside the handleSubmit function with a static name and job value, it works. But if i use inside the handleSubmit function, it doesn't work. Why? and how can i solve this?
import React from "react";
function CreateUser() {
const handleSubmit = (e) => {
e.preventDefault();
fetch("https://reqres.in/api/users", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: `${e.target.name.value}`,
job: `${e.target.job.value}`,
}),
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">Name</label>
<input id="name" name="name" type="text" />
<label htmlFor="job">job</label>
<input id="job" name="job" type="text" />
<input type="submit" value="submit" />
</form>
);
}
export default CreateUser;
Can you check how to use fetch correctly. https://developers.google.com/web/ilt/pwa/working-with-the-fetch-api you need to return response.
Your react code seems fine, not sure how are you trying to handle success and error.
Check following Sandbox which I created using your code.
https://codesandbox.io/s/adoring-breeze-7fx2g?file=/src/App.js

React JS: problem in receiving cookie with axios, which is received from JWT Django

First of all, I had made a POST APIView function using Django and added JWT token in it. This api is basically made for the login purpose. I can transfer all the details in it and recieve a cookie in return.
class LoginView(APIView):
def post(self, request):
email = request.data['email']
password = request.data['password']
user = User.objects.filter(email=email).first()
if user is None:
raise AuthenticationFailed('user not found')
if not user.check_password(password):
raise AuthenticationFailed('Incorrect password')
payload = {
'id': user.id,
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=60),
'iat': datetime.datetime.utcnow()
}
token = jwt.encode(payload, 'secret', algorithm='HS256').decode('utf-8')
response = Response()
response.set_cookie(key='jwt', value=token, httponly=True)
response.data = {
'jwt': token
}
return response
I used POST request using axios in react js and trying to recieve cookie too with the help of "withCredentials: true" yet unable to get the cookie.
import React, { Component } from 'react';
import axios from 'axios';
class Login extends Component {
state = {
email: '',
password: '',
};
handleSubmit(event){
event.preventDefault();
axios({
method: 'post',
url: 'http://127.0.0.1:8000/user/login ',
withCredentials: true,
data: {
email: this.state.email,
password: this.state.password
}
})
.then(data => console.log(data));
}
handleChange(event){
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({[name]:value})
}
render() {
return (
<div>
<h1>LOGIN</h1>
<form onSubmit={this.handleSubmit.bind(this)}>
<div>
<label>Email: </label>
<br />
<input
type="text"
name="email"
onChange={this.handleChange.bind(this)}
value={this.state.email}
/>
</div>
<br />
<div>
<label>Password: </label>
<br />
<input
type="password"
name="password"
onChange={this.handleChange.bind(this)}
value={this.state.password}
/>
</div>
<br />
<button type="submit">Submit</button>
</form>
</div>
);
}
}
export default Login;
I am getting this issue in the console.
Rather than using axios. I had used fetch() which worked for me.
event.preventDefault();
const response = await fetch('http://localhost:8000/user/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
credentials: 'include',
body: JSON.stringify({
email: this.state.email,
password: this.state.password
})
});
console.log(response)
}```

React: How do I carry authentication from login page to redirect page?

In my React project, users log in and then are redirected to the page '/registergig'. This is a protected page that only logged in users should be able to access.
On the register gig page, users are required to input text data that is posted to a firebase database. However when I try and submit data, I get a 403 error returned:
index.js:1 Error: Request failed with status code 403
I'm new to implementing auth so this is all a bit confusing, so how do I make '/registergig' a protected page that allows users to submit information?
Here's the Login component:
import React from 'react'
import Header from './Header'
import Button from '#material-ui/core/Button'
import axios from 'axios'
import {Link} from 'react-router-dom'
class Login extends React.Component {
constructor() {
super();
this.state = {
email: "",
password: "",
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
handleSubmit(e) {
console.log("submit reached");
e.preventDefault();
const loginData = {
email: this.state.email,
password: this.state.password,
};
axios("http://localhost:5000/gig-fort/us-central1/api/login", {
method: "POST",
headers: {
"content-type": "application/json",
},
data: loginData,
})
.then((res) => {
console.log(res.data);
this.props.history.push("/gigregister");
})
.catch((err) => {
console.error(err);
});
}
render() {
return (
<>
<div>
<Header />
</div>
<Link to="/Homepage" style={{ textDecoration: "none" }}>
<h1 className="login-header">Gigs this week</h1>
</Link>
<div className="login-main">
<div className="login">
<h2>Venue login</h2>
<form onSubmit={this.handleSubmit}>
<input
type="text"
name="email"
placeholder="email"
onChange={this.handleChange}
/>
<br></br>
<input
type="password"
name="password"
placeholder="password"
onChange={this.handleChange}
/>
<div className="button">
<Button type="submit">Submit</Button>
</div>
</form>
</div>
<Link to="/venueregister" style={{ textDecoration: "none" }}>
<h2 style={{ color: "#b49650" }}>Register a venue</h2>
</Link>
</div>
</>
);
}
}
export default Login;
Here's the GigRegister component, that takes in user information:
import React from "react";
import Header from "./Header";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
import axios from "axios";
class GigRegister extends React.Component {
constructor() {
super();
this.state = {
name: "",
venue: "",
time: "",
date: "",
genre: "",
tickets: "",
price: "",
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
handleSubmit(e) {
console.log("submit function reached");
e.preventDefault();
const gigData = {
name: this.state.name,
venue: this.state.venue,
time: this.state.time,
date: this.state.date,
genre: this.state.genre,
tickets: this.state.tickets,
price: this.state.price,
};
axios("http://localhost:5000/gig-fort/us-central1/api/createGigListing", {
method: "POST",
headers: {
"content-type": "application/json",
},
data: gigData,
})
.then((res) => {
console.log(res.data);
})
.catch((err) => {
console.error(err);
});
}
setDate() {}
render() {
return (
<div className="gig-register">
<Header />
<h1 className="header-gigReg">Register a gig</h1>
<form onSubmit={this.handleSubmit}>
<TextField
placeholder="Event name"
defaultValue="Event name"
id="name"
name="name"
onChange={this.handleChange}
/>
<TextField
placeholder="Venue"
defaultValue="Venue"
id="venue"
name="venue"
onChange={this.handleChange}
/>
<TextField
placeholder="Time"
defaultValue="Time"
type="time"
label="Enter start time"
id="time"
name="time"
InputLabelProps={{
shrink: true,
}}
inputProps={{
step: 300, // 5 min
}}
onChange={this.handleChange}
/>
<TextField
id="date"
label="Select date"
type="date"
defaultValue="2017-05-24"
InputLabelProps={{
shrink: true,
}}
onChange={(e) => {
this.setState({ date: e.target.value });
}}
/>
<TextField
placeholder="Genre"
defaultValue="Genre"
id="genre"
name="genre"
onChange={this.handleChange}
/>
<TextField
placeholder="Tickets"
defaultValue="Tickets"
id="tickets"
name="tickets"
onChange={this.handleChange}
/>
<TextField
placeholder="Price"
defaultValue="Price"
id="price"
name="price"
onChange={this.handleChange}
/>
<Button type="submit">Submit</Button>
</form>
</div>
);
}
}
export default GigRegister
...and here's the express/firebase functions:
const FBAuth = (req, res, next) => {
let idToken;
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer ')){
idToken = req.headers.authorization.split('Bearer ')[1]
} else {
console.error('No token found')
return res.status(403).json({error: 'Unauthorized'})
}
admin.auth().verifyIdToken(idToken)
.then(decodedToken => {
req.user = decodedToken;
return db.collection('users')
.where('userId', '==',req.user.uid)
.limit(1)
.get()
})
.then(data =>{
req.user.venueName = data.docs[0].data().venueName;
return next();
})
.catch(err => {
console.error('Error while verifying token', err)
return res.status(403).json(err)
})
}
app.post('/createGigListing', FBAuth, (req,res) => {
const newGig = {
venueName: req.user.venueName,
name: req.body.name,
time: req.body.time,
price: req.body.price,
genre: req.body.genre,
tickets: req.body.tickets,
date: req.body.date
}
db
.collection('gig-listing')
.add(newGig)
.then(doc => {
res.json({message: `document ${doc.id} created successfully`})
})
.catch(err =>{
res.status(500).json({error: 'something went wrong'})
console.error(err)
})
})
Your Cloud Functions code expects a Authorization header with a Bearer token in there, but your client-side code is not passing that in this call:
axios("http://localhost:5000/gig-fort/us-central1/api/createGigListing", {
method: "POST",
headers: {
"content-type": "application/json",
},
data: gigData,
})
So you'll have to add a header here, passing in the ID token:
firebase.auth().currentUser.getIdToken().then(function(token) {
axios("http://localhost:5000/gig-fort/us-central1/api/createGigListing", {
method: "POST",
headers: {
"content-type": "application/json",
"Authorization": "Bearer "+token,
},
data: gigData,
})
});
I loosely based this on this code from the functions-samples repo.

Resources