Google ReCaptcha: react-google-recaptcha not verifying correctly - reactjs

I have the following React component for a contact form:
import React from 'react'
import ReCAPTCHA from "react-google-recaptcha";
import {Container, Row, Col, Form, Button } from 'react-bootstrap'
import '../styles/contact.css'
class Contact extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
name: '',
email: '',
company: '',
content: '',
showSuccess: false,
submitting: false,
verified: false,
reply: ''
};
this.handleSuccess = this.handleSuccess.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
this.onChange = this.onChange.bind(this);
}
onChange = (value) => {
console.log("Captcha value:", value);
this.setState({
verified: true
})
};
handleInputChange = event => {
const target = event.target
const value = target.value
const name = target.name
this.setState({
[name]: value,
})
}
handleSuccess = () => {
this.setState({
name: '',
email: '',
company: '',
content: '',
showSuccess: true,
submitting: false,
})
}
handleSubmit = event => {
const url = 'https://xxxxxxxx.execute-api.eu-central-1.amazonaws.com/dev/email/send';
this.setState({
submitting: true
})
const payload = {
name: this.state.name,
email: this.state.email,
company: this.state.company,
content: this.state.content
}
if (this.state.verified) {
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
.then(this.handleSuccess)
.catch(error => alert(error))
event.preventDefault()
}
else {this.setState({reply: "Please verify the ReCaptcha."})}
}
render() {
return (
<section id="contact" name="#contact">
<Container>
<Row className="align-items-center">
<Col lg={{span: 5, order: 1}} xs={{ span: 12, order: 2}} className="form-background">
<Form id="contact-form-bottom" onSubmit={this.handleSubmit}>
<h4 className="h4">Don't be shy, say hi!</h4>
<Form.Group controlId="formBasicEmail">
<Form.Label>Full Name</Form.Label>
<Form.Control
as="input"
type="text"
placeholder="Enter your first name & surname"
name="name"
value={this.state.name}
onChange={this.handleInputChange}
required
/>
</Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control
as="input"
type="email"
placeholder="Enter your email address"
name="email"
value={this.state.email}
onChange={this.handleInputChange}
required
/>
<Form.Text className="text-muted">
We'll never share your email with anyone else.
</Form.Text>
</Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Label>Company Name</Form.Label>
<Form.Control
as="input"
type="text"
placeholder="Enter the name of your company"
name="company"
value={this.state.company}
onChange={this.handleInputChange}
required
/>
</Form.Group>
<Form.Group controlId="exampleForm.ControlTextarea1">
<Form.Label>Details</Form.Label>
<Form.Control
as="textarea"
type="text"
rows="3"
placeholder="How can we help you?"
name="content"
value={this.state.content}
onChange={this.handleInputChange}
required
/>
</Form.Group>
<ReCAPTCHA
className="g-recaptcha"
sitekey="XXXXXXXXXXXXXXXXXXX"
onChange={this.onChange}
theme="dark"
/>
{ this.state.verified ? <p id="error" className="error">{this.state.reply}</p> : null }
{ this.state.showSuccess ? <p id="success" className="success">Thank you, we will be in touch asap.</p> : null }
<Button id="submit" variant="primary" type="submit">
Submit
</Button>
</Form>
</Col>
</Row>
</Container>
</section>
)
}
}
export default Contact
Desired behaviour
I'm using react-google-recaptcha (https://www.npmjs.com/package/react-google-recaptcha) for Recaptcha verification and inserted the component top of the submit button:
<ReCAPTCHA
className="g-recaptcha"
sitekey="XXXXXXXXXXXXXXXXXXXXX"
onChange={this.onChange}
theme="dark"
/>
The onChange function should set state.verfied == true
onChange = (value) => {
console.log("Captcha value:", value);
this.setState({
verified: true
})
};
so that this part of handledSubmit() fires if the reCaptcha was completed and the form gets submitted without page reload:
if (this.state.verified) {
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
.then(this.handleSuccess)
.catch(error => alert(error))
event.preventDefault()
}
otherwise it should render this.state.reply: "Please verify the ReCaptcha." above the submit button.
What it does instead
The submit button works without completing the reCaptcha and submits the form. It reloads the page to http://localhost:8000/?name=Test&email=test&company=test&content=test&g-recaptcha-response=
I know that my workaround using state probably isn't the correct way of using this module, but the react-google-recaptcha docs leave no hint on how to correctly integrate the verification with the reCaptcha API.
Happy for any support on this. Thanks!

I needed to change the onChange function to store the reCaptchaResponse like so:
onChange = (result) => {
this.setState({
verified: true,
reCaptchaResponse: result,
})
};
And secondly I updated the condition in handleSubmit to check for verification much earlier and also integrate the reCaptchaResponse in the payload like so:
handleSubmit = event => {
if (this.state.verified) {
const url = 'https://xxxxxxxxxx.execute-api.eu-central-1.amazonaws.com/dev/email/send';
this.setState({
submitting: true
})
const payload = {
name: this.state.name,
email: this.state.email,
company: this.state.company,
content: this.state.content,
result: this.state.reCaptchaResponse
}
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
})
.then(this.handleSuccess)
.catch(error => alert(error))
event.preventDefault()
} else {
this.setState({
reply: "Please verify the ReCaptcha"
})
}
}

Related

Form is not updating when using hooks

When using React Hooks my inputs are not updating. It means that when I'm updating the input in HTML, the formData is like:
{username: "", password: "", "": "a", undefined: undefined}. What's happening?
export default function Login() {
const [formData, setFormData] = useState({
username: "",
password: "",
});
async function handleSubmit(event: FormEvent) {
event.preventDefault();
const body = {
username: (event.currentTarget as any).username.value,
password: (event.currentTarget as any).password.value,
};
const res = await fetch("/api/login", {
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
},
});
if (res.ok) {
Router.push("/");
}
}
function handleChange(event: FormEvent<HTMLInputElement>) {
setFormData((prevState) => ({
...prevState,
[event.currentTarget?.name]: event.currentTarget?.value,
}));
}
return (
<Layout>
<form onSubmit={handleSubmit}>
<FormInput
label="User name"
placeholder="Enter your username"
type="text"
value={formData.username}
onChange={handleChange}
/>
<FormInput
label="Password"
placeholder="Enter your password"
type="password"
value={formData.password}
onChange={handleChange}
/>
<input type="submit" value="Send" />
<Link href="/register">Create account</Link>
</form>
</Layout>
);
}
FormInput component is just:
type Props = {
label: string;
} & React.HTMLProps<HTMLInputElement>;
export default function FormInput({ label, ...props }: Props) {
return (
<>
<label htmlFor={label}>{label}</label>
<input {...props} />
</>
);
}
You need to implement handleChange as a callback and add the name prop. Use event.target;
export default function Login() {
const [formData, setFormData] = useState({
username: "",
password: "",
});
const handleSubmit = (event: FormEvent) => {
event.preventDefault();
const body = {
username: (event.currentTarget as any).username.value,
password: (event.currentTarget as any).password.value,
};
const res = await fetch("/api/login", {
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
},
});
if (res.ok) {
Router.push("/");
}
}
const handleChange(event: FormEvent<HTMLInputElement>) => {
setFormData((prevState) => ({
...prevState,
[event.target?.name]: event.target?.value,
}));
}
return (
<Layout>
<form onSubmit={handleSubmit}>
<FormInput
label="User name"
placeholder="Enter your username"
type="text"
value={formData.username}
onChange={handleChange}
name="username"
/>
<FormInput
label="Password"
placeholder="Enter your password"
type="password"
value={formData.password}
onChange={handleChange}
name="password"
/>
<input type="submit" value="Send" />
<Link href="/register">Create account</Link>
</form>
</Layout>
);
}

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.

Why is React menu pick not maintaining selection?

I am trying to figure out why the menu pick for a note's Folder Name is not getting selected in the code below. I'm using the tags around the folder options. The user can select the Folder Name for the note being created from the UI, but the UI doesn't maintain the selection. As a result, the note is not getting saved to any of the folders.
import React, { Component } from 'react'
import NotesContext from './notesContext'
import './addNote.css'
class AddNote extends Component {
static contextType = NotesContext
constructor(props) {
super(props);
this.state = {
name: '',
value: '',
id: '',
folderId: '',
content: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
console.log("handleChange value: " + event.target.value);
console.log("handleChange name: " + event.target.name)
this.setState(
{[event.target.name]: event.target.value}
);
}
handleSubmit(event) {
console.log("this.context: " + JSON.stringify(this.context))
event.preventDefault();
let requestOptions = {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"name": this.state.name,
"id": this.state.id,
"folderId": this.state.folderId,
"modified": new Date().toISOString(),
"content": this.state.content
})
};
fetch("http://localhost:9090/notes/", requestOptions)
.then(response => response.json())
.then(result => {
console.log("result:" + JSON.stringify(result));
this.context.addNote(
result.name,
result.id,
result.folderId,
result.modified,
result.content
);
this.props.history.push("/");
})
.catch(error => console.log('error', error));
}
render() {
let notesContext = this.context
return (
<form
className="AddNote"
onSubmit={e => this.handleSubmit(e)}
>
<h1>Create a note</h1>
<label>
Note Name:{' '}
<input
type="text"
value={this.state.name}
className="NameInput"
name="name"
id="name"
onChange={(e) => this.handleChange(e)}
/>
</label>
<label>
Content:{' '}
<textarea
className="ContentInput"
name="content"
id="content"
onChange={e => this.handleChange(e)}
/>
</label>
<label>
Folder:{' '}
<select
value={this.state.folderId} onChange={ (e) => this.handleChange(e)}>
{notesContext.folders.map(folder => {
return(
<option
value={folder.name}
name={folder.name}
key={folder.id}>{folder.name}
</option>
)
})}
</select>
</label>
<input
type="submit"
value="Submit"
className="SubmitButton"
/>
</form>
);
}
}
export default AddNote;
I have a partial Answer at this point. I split up the handleChange method for setting the note and folder. This is now allowing me to create the note in the selected folder -- only if I select a new folder, not the folder selected by default. So I still need to fix that part.
import React, { Component } from 'react'
import NotesContext from './notesContext'
import './addNote.css'
class AddNote extends Component {
static contextType = NotesContext
constructor(props) {
super(props);
this.state = {
name: 'Cows',
id: '',
folderId: '',
content: "",
value: '',
}
this.handleChangeOfNote = this.handleChangeOfNote.bind(this);
this.handleChangeOfFolder = this.handleChangeOfFolder.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChangeOfNote(event) {
//console.log("handleChange value: " + event.target.value);
//console.log("handleChange name: " + event.target.name);
this.setState(
{[event.target.name]: event.target.value}
);
}
handleChangeOfFolder(event) {
this.setState(
{folderId: event.target.value}
);
}
handleSubmit(event) {
event.preventDefault();
let requestOptions = {
method: 'POST',
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"name": this.state.name,
"id": this.state.id,
"folderId": this.state.folderId,
"modified": new Date().toISOString(),
"content": this.state.content
})
};
fetch("http://localhost:9090/notes/", requestOptions)
.then(response => response.json())
.then(result => {
console.log("result:" + JSON.stringify(result));
this.context.addNote(
result.name,
result.id,
result.folderId,
result.modified,
result.content
);
this.props.history.push("/");
})
.catch(error => console.log('error', error));
}
render() {
let notesContext = this.context
return (
<form
className="AddNote"
onSubmit={e => this.handleSubmit(e)}
>
<h1>Create a note</h1>
<label>
Note Name:{' '}
<input
type="text"
value={this.state.name}
className="NameInput"
name="name"
id="name"
onChange={(e) => this.handleChangeOfNote(e)}
/>
</label>
<label>
Content:{' '}
<textarea
className="ContentInput"
name="content"
id="content"
onChange={e => this.handleChangeOfNote(e)}
/>
</label>
<label>
Folder:{' '}
<select
value={this.state.folderId} onChange={(e) => this.handleChangeOfFolder(e)}>
{notesContext.folders.map(folder => {
return(
<option
value={folder.id}
name={folder.name}
key={folder.id}>{folder.name}
</option>
)
})}
</select>
</label>
<input
type="submit"
value="Submit"
className="SubmitButton"
/>
</form>
);
}
}
export default AddNote;
To fix the problem with the default folder getting set, for now I just set the folderId in state, so that it would be there by default.
constructor(props) {
super(props);
this.state = {
name: '',
id: '',
folderId: 'b0715efe-ffaf-11e8-8eb2-f2801f1b9fd1',
content: "",
value: '',
}

React signup page syntax error at return of render function

i have a react sign up page that returns an error at the return of the render method. It shows a syntax error whenever i run the code on the browser. The code is meant to pass data to a server endpoint.I have looked all over and can't find the cause of the error. I would like to know the probable cause of this problem and the line of action or code to correct this error
`import React, { Component } from 'react';
class Register extends Component {
constructor(props) {
super(props);
this.state = {
name:'',
town: '',
long: '',
lat: ''
}
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
onSubmit = (e) => {
e.preventDefault();
const Register = {
name: this.state.name,
town: this.state.town,
long: this.state.long,
lat: this.state.lat
}
}
}
fetch ('https://localhost3000/users/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'name',
city: 'city',
long: 'long',
lat: 'lat'
})
})
.then(function(response){
return response.json();
})
.then(function(Register){
console.log(Register)
});
*render() {
return ( *
<div>
<form className="form-style">
<label>
Name:<br/>
<input name='name' value={this.state.name}
placeholder="Enter Your Farm Name"
onChange={e => this.handleChange(e)}/>
</label><br/>
<label>
Town:<br/>
<input name='town' value={this.state.town}
placeholder="Enter town where farm is located"
onChange={e => this.handleChange(e)}/>
</label><br/>
<label>
Longitude:<br/>
<input name='long' value={this.state.long}
placeholder="Enter Your Farm Longitude"
onChange={e => this.handleChange(e)}/><br/>
Latitude:<br/>
<input name='lat' value={this.state.lat}
placeholder="Enter Your Farm Latitude"
onChange={e => this.handleChange(e)}/>
</label><br/>
<Link><a href="https://www.latlong.net/" target="_blank">
Get Longitude and Latitude of current location here</a></Link><br/>
<button onClick={e => this.handleSubmit(e)}
disabled={!this.state.name}
disabled={!this.state.long}
disabled={!this.state.lat}
disabled={!this.state.town}>
Register</button>
</form>
</div>
)
};
export default Register ;`
You have a misplaced } in your code right after you define the onSubmit function. This closed off your component and made the rest of your code invalid. You're also trying to call fetch inside your component without it being inside any lifecycle-method, function or event. This will lead to a syntax error.
Try this instead :)
import React from "react"
import { Link } from "react-router-dom"
class Register extends React.Component {
constructor(props) {
super(props)
this.state = {
name:'',
town: '',
long: '',
lat: ''
}
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
componentDidMount(){
fetch ('https://localhost3000/users/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'name',
city: 'city',
long: 'long',
lat: 'lat'
})
})
.then(function(response){
return response.json();
})
.then(function(Register){
console.log(Register)
})
}
onSubmit = (e) => {
e.preventDefault()
const Register = {
name: this.state.name,
town: this.state.town,
long: this.state.long,
lat: this.state.lat
}
}
render(){
return (
<div>
<form className="form-style">
<label>
Name:<br/>
<input name='name' value={this.state.name}
placeholder="Enter Your Farm Name"
onChange={e => this.handleChange(e)}/>
</label><br/>
<label>
Town:<br/>
<input name='town' value={this.state.town}
placeholder="Enter town where farm is located"
onChange={e => this.handleChange(e)}/>
</label><br/>
<label>
Longitude:<br/>
<input name='long' value={this.state.long}
placeholder="Enter Your Farm Longitude"
onChange={e => this.handleChange(e)}/><br/>
Latitude:<br/>
<input name='lat' value={this.state.lat}
placeholder="Enter Your Farm Latitude"
onChange={e => this.handleChange(e)}/>
</label><br/>
<Link><a href="https://www.latlong.net/" target="_blank">
Get Longitude and Latitude of current location here</a></Link><br/>
<button onClick={e => this.handleSubmit(e)}
disabled={!this.state.name}
disabled={!this.state.long}
disabled={!this.state.lat}
disabled={!this.state.town}>
Register</button>
</form>
</div>
)
}
}
export default Register

State Value Not Being Set from Default Value on Form Submission

I have a form where two of my input fields have a defaultValue set to prop values. On form submission I am passing the values from other inputs that are set to state properties, but I am not sure how to capture the defaultValue if the values from those two input fields remain unchanged. Is there a method that follows best practices to capture the defaultValue if the value never changes?
import React from 'react';
import { API_ROOT } from '../../../../config/api-config';
//Annotation - Footer - Email Annotation Modal
export default class EmailAnnotationForm extends React.Component {
constructor(props) {
super(props);
this.state = {
csrf: '',
subject: '',
emails: '',
comment: ''
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.handleClearForm = this.handleClearForm.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
console.log(event);
this.setState({
[name]: value
});
console.log(target)
console.log(name)
console.log(value)
console.log(JSON.stringify(this.state));
}
handleFormSubmit(event) {
console.log("handleFormSubmit")
const body = {
csrf: this.state.csrf,
subject: this.state.subject,
emails: this.state.emails,
comment: this.state.comment
};
event.preventDefault();
var route = `${API_ROOT}` + '/api/annotation/' + this.props.annotationId + '/share/email';
fetch(route,
{
method: 'POST',
body: JSON.stringify(body),
compress: false,
headers: {
'X-CSRF-Token': this.state.csrf,
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => {
return res.json();
})
.then(data => {
console.log(data)
handleClearForm()
this.setState({'flash': 'success'});
})
.catch(err => {
console.log(err);
this.setState({'flash': 'error'});
});
}
handleClearForm() {
console.log("handleClearForm")
this.setState({
csrf: '',
subject: '',
emails: '',
comment: ''
})
}
render() {
return (
<div className="annotation-footer__share-form-email">
<form action={"/api/annotation/" + this.props.annotationId + "/share/email"} method="post" onSubmit={this.handleFormSubmit} name="annotationEmailShare" id="share-email-form">
<input type="hidden" name="_csrf" defaultValue={this.props.csrf ? this.props.csrf : ""}/>
<div className="input-group annotation-footer__share-form-email-inputs">
<p><b>Subject:</b></p>
<input type="text" name="subject" className="form-control" defaultValue={this.props.title} onChange={this.handleInputChange}/><br />
</div>
<div className="input-group annotation-footer__share-form-email-inputs">
<p><b>Emails (Comma separate each eamil address):</b></p>
<input type="text" name="emails" className="form-control" onChange={this.handleInputChange}/><br />
</div>
<div className="input-group annotation-footer__share-form-email-inputs">
<p><b>Additional Comment:</b></p>
<textarea name="comment" rows="4" className="form-control" onChange={this.handleInputChange}>{this.state.comment}</textarea><br />
</div>
<button type="submit">Send Email</button>
</form>
</div>
)
}
}
Inputs with DefaultProps:
<input type="hidden" name="_csrf" defaultValue={this.props.csrf ? this.props.csrf : ""}/>
<input type="text" name="subject" className="form-control" defaultValue={this.props.title} onChange={this.handleInputChange}/>
Submitted Value (csrf and subject are not appearing with defaultValues):
{"csrf":"","subject":"","emails":"test#gmail.com","comment":"dsfsdfadsfs"}

Resources