Set state on form submit in a functional component - reactjs

In my react typescript app - I have a login component and a handleLoginRequest function which sets the userMessage value:
function Login() {
let [userMessage, setUserMessage] = useState("");
return (
<form className="form-inline" onSubmit={(e) => {
setUserMessage(handleLoginRequest(e))
}} >
<label className="mr-sm-2">Email address:</label>
<input type="email" className="form-control mb-2 mr-sm-2" placeholder="Enter email" id="email" />
<label className="mr-sm-2">Password:</label>
<input type="password" className="form-control mb-2 mr-sm-2" placeholder="Enter password" id="password" />
<button type="submit" className="btn btn-primary mb-2">Submit</button>
{userMessage}
</form>
);
}
Update: handleLoginRequest is a API request
const handleLoginRequest = (event: any): any => {
event.preventDefault();
const data = {
email: event.target.email.value,
password: event.target.password.value
};
axios.post(`${process.env.REACT_APP_HTTP_PROXY}/api/v1/login`, data)
.then(res => {
console.log(res.data);
return res.data;
})
.catch(err => {
console.log(err);
return err.message;
});
}
Expected behavior:
When the form is submitted, the function setUserMessage(handleLoginRequest(e)) is called. I expect that it update the value of userMessage to login request received.
Actual result:
No change in the value of userMessage
What is the fix here?

Updated answer per the question modification
The issue is stemming from the fact you're trying to setState based on a axios post request. Axios requests are asynchronous, meaning they will happen out of order with the program control flow. Therefore, to solve this issue, it is important you only make a call to setUserMessage when the request is complete.
Example Code:
axios.post(`${process.env.REACT_APP_HTTP_PROXY}/api/v1/login`, data)
.then(res => {
setUserMessage(res.data);
})
.catch(err => {
// Do Something with error response
setUserMessage("Error: Something with the request went wrong.");
});
I will link a codesandbox to demonstrate:
https://codesandbox.io/s/focused-leakey-0jer4

Related

i want to show details on same page

i am developing an application i.e supply chain management application on reactJS, NodeJS and blockchain.
Frontend code:
import React, { Component } from 'react'
import { useState, useEffect } from "react";
import axios from "axios";
import { useNavigate } from 'react-router-dom';
const SignUp = () => {
const navigate = useNavigate();
const flag=0;
const [data, setData] = useState({
uname: "",
email: "",
location: "",
budget: "",
password: ""
});
const handleChange = (e) => {
const value = e.target.value;
setData({
...data,
[e.target.name]: value
});
};
const handleSubmit = (e) => {
e.preventDefault();
const userData = {
uname: data.uname,
email: data.email,
location: data.location,
budget: data.budget,
password: data.password
};
axios
.post("http://localhost:8080/api/signup/", userData)
.then((response) => {
console.log(response);
})
.catch((error) => {
if (error.response) {
console.log(error.response);
console.log("server responded");
} else if (error.request) {
console.log("network error");
} else {
console.log(error);
}
});
navigate(`/home`)
};
return (
<form>
<h3>Sign Up</h3>
<div className="mb-3">
<label>User Name</label>
<input
type="text"
name="uname"
value={data.uname}
className="form-control"
placeholder="User name"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label>Email address</label>
<input
type="email"
name="email"
value={data.email}
className="form-control"
placeholder="Enter email"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label>Location</label>
<input
type="text"
name="location"
value={data.location}
className="form-control"
placeholder="Location"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label>Budget</label>
<input
type="Number"
name="budget"
value={data.budget}
className="form-control"
placeholder="Budget"
onChange={handleChange}
/>
</div>
<div className="mb-3">
<label>Password</label>
<input
type="password"
name="password"
value={data.password}
className="form-control"
placeholder="Enter password"
onChange={handleChange}
/>
</div>
<div className="d-grid">
<button type="submit" onClick={handleSubmit}className="btn btn-primary">
Sign Up
</button>
</div>
<p className="forgot-password text-right">
Already registered sign in?
</p>
</form>
);
};
export default SignUp;
here if user successfully registered then i want to show deatils of the user on the same page. how should i do that?
i have attached the code and the screenshot of the page.
currently i am on my account page.
Inside of your handle submit
You can just navigate after the axios.then callback
Or if you want the behavior to be that user submits -> register success -> show success -> then redirect, you can setTimeout for say 1000ms and then navigate.
axios
.post("http://localhost:8080/api/signup/", userData)
.then((response) => {
console.log(response);
})
.then(() => {
setTimeout(() => navigate(`/home`), 1000);
}
.catch((error) => {
if (error.response) {
console.log(error.response);
console.log("server responded");
} else if (error.request) {
console.log("network error");
} else {
console.log(error);
}
});
If you mean, show the user data after a successful registration and assuming you're calling an api to register the user and you're getting the user details back on success, you can handle that in your handleSubmit method.
Here's an example
const showUserDetails = (userDetails) => {
// Code that shows user details
// Probably using state
};
const handleSubmit = (e) => {
e.preventDefault();
const userData = {
...
axios
.post("http://localhost:8080/api/signup/", userData)
.then((response) => {
// handle here
showUserDetails(response);
})
.catch((error) => {
if (error.response) {
...
} else {
console.log(error);
}
});
};

How to send form data to email in React JS?

I have to send form datas to an email address.
How can I do?
I did some research and I understand that you have to use a library to do this. correct?
What do you suggest?
I think this one might be worth looking into - https://www.emailjs.com/docs/sdk/send-form/
If you are looking for implementation for Reactjs then use like this :
// install #emailjs/browser
import React, { useRef } from 'react';
import emailjs from '#emailjs/browser';
export const ContactUs = () => {
const form = useRef();
const sendEmail = (e) => {
e.preventDefault();
// service_id, templte_id and public key will get from Emailjs website when you create account and add template service and email service
emailjs.sendForm('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', form.current,
'YOUR_PUBLIC_KEY')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
};
return (
<form ref={form} onSubmit={sendEmail}>
<label>Name</label>
<input type="text" name="user_name" />
<label>Email</label>
<input type="email" name="user_email" />
<label>Message</label>
<textarea name="message" />
<input type="submit" value="Send" />
</form>
);
};

Unable to retrieve API data using axios

I'm trying to build a simple login using an API but keep facing errors
import React from "react";
import { useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
export default function Login() {
const navigate = useNavigate();
const [formData, setFormData] = useState({
uid: "",
password: "",
blocked: 0
});
const handleSubmit = (e) => {
e.preventDefault();
console.log(formData);
const data = JSON.stringify(formData);
console.log(data);
axios
.post("https://myphysio.digitaldarwin.in/api/login/", data)
.then(function (response) {
console.log(response);
console.log("Successfully Logged in ");
navigate("/success");
})
.catch(function (error) {
console.log(error);
});
};
return (
<form onSubmit={handleSubmit}>
<h3>Login</h3>
<div className="form-group">
<label>uid Name</label>
<input
name="uid"
className="form-control"
placeholder="Enter your uid Name"
value={formData.uid}
onChange={(e) => setFormData({ ...formData, uid: e.target.value })}
/>
</div>
<div className="form-group">
<label>Password</label>
<input
type="password"
name="password"
className="form-control"
placeholder="Enter password"
value={formData.password}
onChange={(e) =>
setFormData({ ...formData, password: e.target.value })
}
/>
</div>
<button type="submit" className="btn btn-primary btn-block">
Submit
</button>
</form>
);
}
The error I keep facing is
console log of error
POST https://myphysio.digitaldarwin.in/api/login/ 500 (Internal Server Error)
Error: Network Error
at createError (createError.js:16:1)
at XMLHttpRequest.handleError (xhr.js:117:1)
POST https://myphysio.digitaldarwin.in/api/login/ net::ERR_CONTENT_LENGTH_MISMATCH 500 (Internal Server Error)
All your errors come from the backend so I suggest you to post a question in the django section (I looked at the link and I was django framework so I assume that you use django). Maybe you don't want to stringify your formData (usually it's common to send a json in a post request).

Passing data from front end to route in backend React

I am currently new to using React and express, I wish to send data which i have received from a form. The data i would like to send back is the UserInfo or email which is in the state. However I am extremely unsure how I am supposed to go about this request.
class ForgotPassword extends Component {
constructor() {
super()
this.state = {
email:'',
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
componentDidMount = () =>{
// this.fetchUserInfo();
}
handleChange = (e) => {
this.setState ({
[e.target.id]: e.target.value
})
console.log(this.state);
}
handleSubmit = async (e) => {
e.preventDefault();
const userInfo = {
email : this.state.email
};
fetch("/forgotpassword", {
method: "POST",
body: JSON.stringify(userInfo),
headers: { "Content-Type": "application/json" }
})
.then(response => {
return response.json();
})
.then(jsonData => {
console.log(jsonData);
})
.catch(err => {
console.log("Error with data fetch " + err);
});
};
This is my form...
<div className='row'>
<div className='col'></div>
<div className='col card form'>
<h1 id="title">Reset Password</h1>
<h5 id="passinstruc">Please enter your email to reset your password</h5>
<form id="forgotpass" onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email </label>
<input onChange={this.handleChange} type="email" className="form-control" id="email" aria-describedby="emailHelp" placeholder="Enter email" value={this.state.email} />
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<button id="loginbtn" type="submit" className="btn btn-primary btn-lg btn-block" >Submit</button>
<br/>
<div className='division'>
<Link to="/register" className='btn btn-primary btn-lg btn-block' id="registerbtn" > Create your account here</Link>
</div>
</form>
</div>
In my backend I am getting a POST /forgotpassword 404 message but I dont know why. Help would be much appreciated.
This is my backend route where I will be sending the information
var express = require('express');
var router = express.Router();
var connection = require ('../connection');
var email = require ('./sendEmail');
router.post('/forgotpassword', function(req, res, next) {
console.log(req.email);
var userEmail = req.email;
var text = "Follow the instructions below to reset your password"
email.sendEmailWithTemplate(userEmail,'PetS.o.S Password Reset', text);
});
For sending data you will need the domain name or ip address of your server.
Once you obtained that, you can use jQuery.get - https://api.jquery.com/jQuery.get/
or jQuery.post -
https://api.jquery.com/jQuery.post/
Or if you are not using jQuery, use XMLHttpRequest -
https://www.w3schools.com/xml/xml_http.asp
Instead of sending data in body send it in response.
https://www.freecodecamp.org/news/create-a-react-frontend-a-node-express-backend-and-connect-them-together-c5798926047c/
fetch('/api/getList')
.then(res => res.json())
.then(list => this.setState({ list }))
https://dev.to/nburgess/creating-a-react-app-with-react-router-and-an-express-backend-33l3

Event code is not executed after default page reload

On onSubmit form event I'd like to send some data to the server with PUT or POST method and then refresh the page, but page reloads without executing the rest of the event code. Adding line event.preventDefault() fixes the issue but blocks reloading. What am I missing?
Event code:
handleFormSubmit = (event, requestType, articleID) => {
const title = event.target.elements.title.value;
const content = event.target.elements.content.value;
switch ( requestType ) {
case 'post':
return axios.post('http://127.0.0.1:8000/api/', {
title: title,
content: content
})
.then(res => console.log(res))
.catch(error => console.err(error));
case 'put':
return axios.put(`http://127.0.0.1:8000 /api/${articleID}/`, {
title: title,
content: content
})
.then(res => console.log(res))
.catch(error => console.err(error));
}
}
Form code:
<Form onSubmit={(event) => this.handleFormSubmit(
event,
this.props.requestType,
this.props.articleID )}>
<FormItem label="Title" >
<Input name="title" placeholder="Put a title here" />
</FormItem>
<FormItem label="Content" >
<Input name="content" placeholder="Enter some content ..." />
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit">{this.props.btnText}</Button>
</FormItem>
</Form>
You need to programmatically reload your page after the form has been submitted successfully, or show an error message when there is no response or any server error:
class App extends React.Component {
handleSubmit = e => {
e.preventDefault();
return axios
.post("https://reqres.in/api/login", {
email: "title",
password: "content"
})
.then(res => {
alert(res.data.token);
location.reload();
})
.catch(error => console.log(error));
};
render() {
return (
<div className="App">
<form onSubmit={this.handleSubmit}>
<input type="text" placeholder="Email" />
<input type="password" placeholder="Password" />
<button type="submit">Submit</button>
</form>
</div>
);
}
}
Here is a demo :https://codesandbox.io/s/j7j00nq705
You can use event.preventDefault(). But you should use react-router library history.push() to manually load another component after your request completes.
case 'post':
return axios.post('http://127.0.0.1:8000/api/', {
title: title,
content: content
})
.then(res => {
console.log(res);
// using "history.push()" to load another component
this.props.history.push('/somePage')
})
.catch(error => console.err(error));
Your above Form component must be routed using react-router or Form component must be in a Component routed using react-router.

Resources