React form onSubmit function not being called - javascript

I have a form on my page with an onSubmit function that I want to be called, but it doesn't seem to be triggered as the console.log never appears.
import React, { Component } from 'react'
class EmailSignUp extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
lastName: '',
error: false
}
this.handleChange = this.handleChange.bind(this)
this.onSubmitForm = this.onSubmitForm.bind(this)
}
onSubmitForm (e) {
console.log('function has run');
e.preventDefault()
let formData = new FormData(e)
const { formAction } = this.props
const requestOptions = {
method: 'POST',
body: formData
}
fetch(formAction, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error))
}
handleChange (e) {
const value = e.target.value
const inputId = e.target.id
this.setState(() => ({
[inputId]: value
}))
}
render () {
const { error } = this.state
return (
<div id='email-form' className='container'>
<form
name='form'
id='form'
onSubmit={this.onSubmitForm}
method='post'
>
<div className='form-group'>
<label htmlFor='email'>Email</label>
<input
type='email'
name='Email'
className='form-control'
id='email'
placeholder='youremail#email.com'
onChange={this.handleChange}
value={this.state.email}
required
/>
</div>
<div className='form-group'>
<label htmlFor='lastName'>Last name</label>
<input
type='text'
name='lastName'
className='text form-control'
id='lastName'
placeholder='Last Name'
onChange={this.handleChange}
value={this.state.lastName}
required
/>
</div>
<button
type='submit'
name='Submit'
value='Subscribe'
className='btn btn-primary item_cta'
readOnly
/>
</form>
{error && <p>{error}</p>}
</div>
)
}
}
export default EmailSignUp

Running your code results in the error 'Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'. The actual form element would be on target of the submit event. Try the following by updating e to e.target:
let formData = new FormData(e.target);
const { formAction } = this.props;
Also remove method from the form element. In addition, remove readOnly from button. It is not meant to be a self closing element like a br:
<button
type="submit"
name="Submit"
value="Subscribe"
className="btn btn-primary item_cta"
>submit</button>
Hopefully that helps!

Related

where to call the Axios post request in reactjs

I have a form,thats data are saved in the state to be sent to the backend server.
i am handling the form with handleSubmit function and useEffect hook, where the handleSubmit prevents the form from being submitted unless it calls the validation function, in the useEffect I check if there are any errors using if condition and then console.log my data.
now I want to post the data hold in the state -the state is sent as a props to me- but I am confused whether to put the request in the HandleSubmit function or in the useEffect inside the body of the if condition.
import react, { Component, useState, useEffect } from 'react';
import {useNavigate } from 'react-router-dom';
import axios from 'axios';
import './sign.css';
const SignA = (props) => {
const navigate = useNavigate();
const [formErrors, setFormErrors] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
const handleSubmit = (err) => {
err.preventDefault();
setFormErrors(validate(props.data));
setIsSubmit(true);
}
useEffect(() => {
console.log(Object.keys(formErrors).length);
if (Object.keys(formErrors).length === 0 && isSubmit) {
console.log('console the props data', props.data)
//here is where I think the post request should be put
if (isSubmit) {
return (navigate('/profileadmin'))
}
}
}, [formErrors])
const validate = (values) => {
const errors = {};
const regex = /^[^\s#]+#[^\s#]+\.[^\s#]{2,}$/i;
if (!values.firstname) {
errors.firstname = 'firstname is required!';
}
if (!values.lastname) {
errors.lastname = 'lastname is required!';
}
if (!values.mobile) {
errors.mobile = 'mobile is required!';
}
if (!values.email) {
errors.email = 'email is required!';
} else if (!regex.test(values.email)) {
errors.email = 'this is not a valid email format!'
}
return errors;
}
return (
<div className='signup'>
<form onSubmit={handleSubmit} >
<div className="container">
<h1>Sign Up</h1>
<div className="name">
<div>
<input
type="text"
placeholder="First name"
name="firstname"
id='firstName'
value={props.data.firstname}
onChange={props.change}
/>
</div>
<div>
<input
type="text"
placeholder="Last name"
name="lastname"
value={props.data.lastname}
onChange={props.change}
/>
</div>
</div>
<p className='errorMsg'>{formErrors.firstname}</p>
<p className='errorMsg'>{formErrors.lastname}</p>
<br />
<div>
<input
type="text"
placeholder="Business mobile number"
name="mobile"
value={props.data.mobile}
onChange={props.change}
/>
<p className='errorMsg'>{formErrors.mobile}</p>
<br />
<input
type="text"
placeholder="Email Adress"
name="email"
value={props.data.email}
onChange={props.change}
/>
<p className='errorMsg'>{formErrors.email}</p>
<br />
</div>
</div>
<br />
<div className="checkbox">
<label>
<input type="checkbox" className="check" />i’ve read and agree with <a href="url" >Terms of service</a>
</label>
</div>
<div className="clearfix">
<button type="submit" className="signupbtn">Sign Up</button>
</div>
</div>
</form >
</div >
)
}
export default SignA;
this is the request
axios.post('', props.data)
.then(res => console.log('post res', res))
.catch(error => {
console.error('There was an error in post request!', error);
});
You don't necessarily need useEffect here.
Here is how you can implement such thing:
Declare a state to hold form values:
const [formData, setFormData] = useState({})
Declare function to set the state:
const handleChange = (name, value) => {
setFormData({...formData, [name]: value})
}
Input onChange to capture:
// handleChange has two parameters
<input
type="text"
placeholder="First name"
name="firstname"
id='firstName'
value={props.data.firstname}
onChange={(event) => handleChange('firstName', event.target.value)}
/>
function for calling post axios post request
const handleSubmit = () => {
//check for validations code here
// if validations are right then post request here
// this will give you all the fields like firstName: "", lastName: ""
let requestBody = {
...formData
}
axios.post("url", requestBody).then((res)=> {
//your code here
})
}

Form Validation - react

index.js
import React, { useState, useEffect } from 'react';
import Axios from 'axios';
import { ToastContainer, toast } from 'react-toastify';
import { useHistory } from 'react-router-dom';
import 'react-toastify/dist/ReactToastify.css';
const AddRequest = () => {
const [request, setRequest] = useState({
product_name: '',
description: '',
product_img: '',
});
const [error, setError] = useState({
product_error: ''
})
const handleChange = e => {
e.preventDefault();
const {name, value} = e.target;
let formError = {...error};
switch(name) {
case "product_error":
formError.product_error =
value.length < 0 ? "Required" : "";
break;
default:
break;
}
setError({formError, [name]: value});
console.log(error)
setRequest({ ...request, [e.target.name]: e.target.value });
};
const headers = {
'x-access-token': localStorage.getItem('accessToken'),
'content-type': 'multipart/form-data'
}
const handleImageChange = async e => {
e.preventDefault();
setRequest({ ...request, [e.target.name]: e.target.files });
};
const handleSubmit = async e => {
e.preventDefault();
const formData = new FormData()
for (const file of request.product_img) {
formData.append('product_img', file)
}
formData.append('product_name', request.product_name)
formData.append('description', request.description)
await Axios.post(config.api, formData, {
headers: headers
})
.then(res => {
toast.success('Added Successfully!', {
position: "top-right",
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
});
})
.catch(e => {
console.log(e)
toast.error('not Added', {
position: "top-right",
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
});
})
setTimeout(function () {
history.push('/')
}, 1500);
};
return (
<>
<ToastContainer />
<form onSubmit={e => handleSubmit(e)} noValidate>
<div className="form-group">
<label htmlFor='product_name'>Product Name:</label>
<input type="text" name="product_name" id="product_name" placeholder="Enter Product Name" className="form-control" noValidate onChange={e => handleChange(e)} />
{errors.product_error}
</div> =====>>> This is required it must give error if left empty
<div className="form-group">
<label htmlFor='description'>Description:</label>
<input type="text" name="description" id="description" placeholder="Description" className="form-control" onChange={e => handleChange(e)} />
</div>
</div> =====>>> This is required it must give error if left empty
<div className="form-group">
<label htmlFor='product_img'>Product Image:</label> <br />
<input type="file" multiple name="product_img" id="product_img" onChange={e => handleImageChange(e)} />
</div>
<button type="submit" className="btn btn-success"> Add Request Rekko </button>
</form>
</>
)
};
export default AddRequest
Everything is working fine but form validation is not working. I am new to react and tried many things but still, it is not working. Can anyone help me with form validation? I only want all 3 fields to be required. It shows the message that this field is required if someone submits a form without entering anything.
You can simply add the tag required inside the input, like this:
<input type="file" multiple name="product_img" id="product_img" onChange={e => handleImageChange(e)} required />

How can I redirect to correct page when successfully submitting form information?

As of now, I'm successfully inserting information into the database (SQL, phpMyAdmin) via Home.js but the problem is that every time the user enters information & hits submit, it gets redirected to my demo.php file (not provided) instead of Next.js.
In other words, how can I make it so that upon the user information successfully entering the database and go to the next page? (Next.js)?
What am I doing wrong and how can I fix this?
Here's Home.js:
import React, { Component } from 'react';
import Next from '../Home/Next';
class Home extends Component {
constructor(props) {
super(props);
this.state = {
show: false
};
this.getPHP = this.getPHP.bind(this);
this.goNext = this.goNext.bind(this);
}
getPHP() {
fetch(`http://localhost/demo_react/api/demo.php`, {
method: 'POST'
}).then(res => res.json())
.then(response => {
console.log('response');
console.log(response);
});
}
goNext() {
this.setState({show: true});
}
render() {
const next = this.state.show;
if(next) {
return <Next/>;
}
return (
<div>
<br/>
<form className="form-control" action="http://localhost/demo_react/api/demo.php" method={"POST"} encType="multipart/form-data">
<input type="text" name="username"/>
<input type="text" name="password"/>
<input type="submit" value="submit" onClick={this.getPHP & this.goNext} name={"submit"}/>
</form>
</div>
);
}
}
export default Home;
Here's Next.js:
import React, { Component } from 'react';
class Next extends Component {
render() {
return(
<h1>made it</h1>
);
}
}
export default Next;
You need to remove the action property from your form and call getPHP() when form is submitted. Also, it's better to have controlled inputs (state of component change when input change). See this for more info: Get form data in Reactjs
<form className="form-control" onSubmit={e => this.getPHP(e)}>
<input type="text" name="username" value={this.state.username} onChange={e => this.setState({ username: e.target.value })} />
<input type="text" name="password" value={this.state.password} onChange={e => this.setState({ password: e.target.value })} />
<input type="submit" value="submit" name="submit" />
</form>
You can access to form values directly in getPHP() method because inputs are now controlled:
constructor(props) {
super(props);
this.state = {
show: false,
username: '',
password: '',
};
}
getPHP(e) {
e.preventDefault();
const { username, password } = this.state;
const formData = new FormData();
formData.append('username', username);
formData.append('password', password );
fetch(`http://localhost/demo_react/api/demo.php`, {
method: 'POST',
headers: new Headers({ 'Content-Type': 'multipart/form-data' }),
body: formData,
})
.then(res => res.json())
.then(response => {
console.log('response');
console.log(response);
this.goNext();
});
}
At the end, you can goNext() when the fetch succeed.

How can I get the data of form on submit?

How can I get the data of form on submit?
import React, { Component } from 'react';
import Axios from 'axios';
class Register extends Component {
submitHandler = (event) => {
event.preventDefault();
var url = '';
var data = {
returnSecureToken:true,
email:this.email,
password:this.password
}
Axios.post(url,data)
.then(response => {
console.log(response);
})
.catch(err =>{
console.log(err);
})
}
render() {
var listClasses = "";
return(
<div>
<h1>Registrati</h1>
<form onSubmit={this.submitHandler}>
<input type="password" className={listClasses} value={this.props.value} placeholder="password" name="password"/>
<input type="email" className={listClasses} value={this.props.value} placeholder="email" name="email"/>
<input type="submit" value="submit"/>
</form>
</div>
);
}
}
export default Register;
I want to send my data by post. I tried to find into my object this but I don't see my data after submit.
The best way to do it is to make the component, uncontrolled component and hook up the change event handlers for each field.
Would be better than using refs that break the encapsulation.
import React, { Component } from 'react';
import Axios from 'axios';
class Register extends Component {
state = {
emailAddress: '',
password: ''
}
submitHandler = (event) => {
const {
emailAddress,
password
} = this.state;
event.preventDefault();
var url = '';
var data = {
returnSecureToken: true,
email: emailAddress,
password: password
}
Axios.post(url, data)
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
})
}
handlePasswordChange = (event) => {
this.setState({ password: event.target.value });
}
handleEmailChange = (event) => {
this.setState({ emailAddress: event.target.value });
}
render() {
var listClasses = "";
return (
<div>
<h1>Registrati</h1>
<form onSubmit={this.submitHandler}>
<input onchange={this.handlePasswordChange} type="password" className={listClasses} value={this.props.value} placeholder="password" name="password" />
<input onchange={this.handleEmailChange} type="email" className={listClasses} value={this.props.value} placeholder="email" name="email" />
<input type="submit" value="submit" />
</form>
</div>
);
}
}
export default Register;

Cannot Get ReactJS Component to Update

I'm attempting to update an area on my page once a fetch() call has been made with the resulting error message from the fetch() call. The fetch() call is executed when the form button is submitted.
When fetch() has completed, I have written ErrorMessage(data['Result']); which I thought would pass data['Result'] as the props. You can see in my render that I have <ErrorMessage error="Original Message" /> which is what I thought would update with the message from the fetch() call.
Please see my full code below for this page:
import React from 'react';
import './css/LoginForm.css';
function ErrorMessage(props) {
return (
<p id="error-message">
{props.error}
</p>
)
}
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(event) {
event.preventDefault();
var loginData = {
username: this.state.username,
password: this.state.password
}
fetch('/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
loginData: loginData
})
})
.then(function(response) {
return response.json();
})
.then(function(data) {
if (data['Result']) {
console.log(data['Result']);
ErrorMessage(data['Result']);
}
})
.catch(function(error) {
console.log('Error: ', error);
});
}
render() {
return (
<div id="login-form-container">
<form id="login-form" onSubmit={this.handleSubmit} method="POST">
<ErrorMessage error="Original Message" />
<input
type="text"
name="username"
placeholder="username"
autoComplete="username"
onFocus={(e) => e.target.placeholder = ''}
onBlur={(e) => e.target.placeholder = 'username'}
value={this.state.username}
onChange={this.handleInputChange}
required
></input>
<input
type="password"
name="password"
placeholder="password"
autoComplete="current-password"
onFocus={(e) => e.target.placeholder = ''}
onBlur={(e) => e.target.placeholder = 'password'}
value={this.state.password}
onChange={this.handleInputChange}
required
></input>
<button type="submit" name="submit">Login</button>
<p className="forgotten-password">Forgotten your password?</p>
</form>
</div>
);
}
}
export default LoginForm;
This may be completely wrong as I am struggling to understand exactly how a component works in ReactJS, so I apologise in advance. Thank you for any insight.
Creating a component when your fetch is complete will not affect what is returned from the render method of your LoginForm component.
You could instead set the error message in the LoginForm state, and use that as props for the ErrorMessage component in the render method.
Example
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
error: "Original Message"
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
// ...
handleSubmit(event) {
event.preventDefault();
var loginData = {
username: this.state.username,
password: this.state.password
};
fetch("/login", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
loginData: loginData
})
})
.then((response) => {
return response.json();
})
.then((data) => {
if (data["Result"]) {
console.log(data["Result"]);
this.setState({ error: data["Result"] });
}
})
.catch((error) => {
console.log("Error: ", error);
});
}
render() {
return (
<div id="login-form-container">
<form id="login-form" onSubmit={this.handleSubmit} method="POST">
<ErrorMessage error={this.state.error} />
<input
type="text"
name="username"
placeholder="username"
autoComplete="username"
onFocus={e => (e.target.placeholder = "")}
onBlur={e => (e.target.placeholder = "username")}
value={this.state.username}
onChange={this.handleInputChange}
required
/>
<input
type="password"
name="password"
placeholder="password"
autoComplete="current-password"
onFocus={e => (e.target.placeholder = "")}
onBlur={e => (e.target.placeholder = "password")}
value={this.state.password}
onChange={this.handleInputChange}
required
/>
<button type="submit" name="submit">
Login
</button>
<p className="forgotten-password">Forgotten your password?</p>
</form>
</div>
);
}
}

Categories

Resources