Form data being deleted after React-Recaptcha is clicked - reactjs

I am using react-recaptcha on a form on my site. Everything works fine, but when I click the recaptcha, when it returns success, all the form data is deleted. I can of course re-enter it, but that's a terrible UI. Why is it being deleted, and how can I prevent it? Thanks.
Script tag in my index.html file:
<script src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>
Component
const RequestADemo = () => {
const [values, setValues] = useState({
recaptcha_verified: false
});
const handleSubmit = (e) => {
if (e) { e.preventDefault() };
if (values.recaptcha_verified) {
requestdemo();
}
};
const handleChange = (e) => {
e.persist();
setValues((values) => ({ ...values, [e.target.name]: e.target.value }));
};
const requestdemo = () => {
let firstname = values.firstname;
fetch("/requestdemo", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ firstname })
})
.then((res) => res.json())
.then((json) => {
console.log("success");
})
.catch((err) => { console.log("err : ", err) });
}
const recaptchaVerified = (response) => {
setValues({...values, recaptcha_verified: true });
}
return (
<div>
<form onSubmit={ handleSubmit }>
<div className="field">
<label className="label">First Name</label>
<div className="control">
<Input className="input" type="text" name="firstname" onChange={ handleChange } value={ values.firstname || "" } required />
</div>
</div>
<Recaptcha
sitekey="6Lxxxxxxxxxxxxxx"
render="explicit"
verifyCallback={recaptchaVerified}
/>
<button type="submit" className="button is-block is-info is-fullwidth">Submit</button>
</form>
</div>
);
};
export default RequestADemo;

Related

I don't understand where the id comes from when creating a new json element in a form (React Hooks)

I have a CRUD form with React Hooks that works correctly, the problem is that I have not indicated that the item is created with a unique ID and yet it has it. Having a unique ID is something that interests me, but I don't understand where it comes from. Does any part of the code cause it to be created? I'm very confused.
Im using JSON Server.
This is the json:
{
"posts": [
{
"id": 15,
"title": "ho",
"author": "Autor de ejemplo",
"content": "Contenido."
}
]
}
This is the fetch with the POST method:
export function setPost(posts: IPost) {
return fetch('http://localhost:3004/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(posts)
})
.then(response => response.json())
}
And this is the form:
interface ErrorMessageProps {
message: string;
}
const ErrorMessage: React.FC<ErrorMessageProps> = props => {
return (
<div className="errorEmpty">
{props.message}
</div>
);
};
const New: React.FC = () => {
const [newPost, setNewPost] = useState({
id: Number(''),
title: '',
author: '',
content: ''
})
const [error, setError] = useState('')
let navigate = useNavigate();
const handleInputChange = (e: React.FormEvent<HTMLInputElement>) => {
console.log((e.target as HTMLInputElement).value)
setNewPost({
...newPost,
[(e.target as HTMLInputElement).name]: (e.target as HTMLInputElement).value
})
};
const createPost = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!newPost.title || !newPost.author || !newPost.content) {
setError("¡No dejes campos vacíos!")
} else {
setPost(newPost);
navigate("/");
}
}
return (
<div className="containerHomepage">
<form className="formulari" onSubmit={createPost}>
<div className="containerBreadCrumb">
<ul className="breadCrumb">
<li>Posts</li>
</ul>
</div>
<div className="containerTitleButton">
<input
className=""
type="text"
placeholder='Post title'
name="title"
onChange={handleInputChange}
></input>
<button
className="button"
type="submit"
>Save</button>
</div>
<div className="containerEdit">
<input
className="editAuthor"
type="text"
placeholder='Author'
name="author"
onChange={handleInputChange}
></input>
<input
className="editContent"
type="textarea"
placeholder='Content'
name="content"
onChange={handleInputChange}
></input>
< ErrorMessage
message={error}
/>
</div>
</form>
</div>
);
};
// ========================================
export default New;

React js update form value using useState

I have a React functional component, a form accepting information for events. I need to send the filled in form info using a POST request. My formData state is not updating, I have tried different onChange functions to try and get this to work. Any ideas where I am going wrong?
`
import styled from 'styled-components';
import axios from 'axios';
import Input from './Input';
import react, {useState, useEffect} from "react";
import DateTimePicker from 'react-datetime-picker';
import TimePicker from "react-time-picker";
import DatePicker from "react-date-picker";
const url = 'http://localhost:5000/events/create'
const EventForm = (props)=> {
const [dateValue, onChangeDate] = useState(new Date());
const [timeValue, onChangeTime] = useState();
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
contactEmail: '',
eventTitle: '',
eventDescription: '',
})
function onChange (e) {
let name = e.target.name ;
let value = e.target.value;
let formObj = { ...formData };
setFormData({ ...formData, [name]: value });
console.log(formData)
}
const body = {
firstName: formData.firstName,
lastName: formData.lastName,
contactEmail: formData.contactEmail,
eventTitle: formData.eventTitle,
eventDescription: formData.eventDescription,
eventDate: dateValue,
eventTime: timeValue,
}
const postFormData = async (e) => {
console.log(formData)
e.preventDefault()
await axios({
method: 'post',
url: url,
data: body,
})
.then((response) => {
console.log(response)
})
.catch(error => console.log(`Error: ${error}`));
}
// const postFormData = async (e) => {
// e.preventDefault()
// let newEvent = await fetch("http://localhost:5000/events/create",
// {
// method: "POST",
// headers: {
// 'Content-Type': 'application/json',
// 'Accept': 'application/json'
// },
// body: JSON.stringify(body)
// });
// newEvent = await newEvent.json();
// console.log(newEvent);
// }
useEffect(() => {
return () => {
console.log(formData.firstName)
}
})
return (
<form onSubmit={props.onSubmit}>
<>
{/* <DateTimePicker onChange={onChange} value={value} minDate={new Date()}/> */}
<StyledForm onSubmit={postFormData}>
<label>
First Name
</label>
<Input
name={"firstName"}
placeholder={"First Name"}
type={"text"}
value={formData.firstName}
onChange={(e) => setFormData({ ...formData, firstName: e.target.value})}
/>
<label>
Last Name
</label>
<Input
name={"lastName"}
placeholder={"Last Name"}
type={"text"}
onChange={onChange}
/>
<label>
Contact Email
</label>
<Input
name={"contactEmail"}
placeholder={"Email"}
type={"email"}
onChange={onChange}
/>
<label>
Event Date
</label>
<DatePicker onChange={onChangeDate} value={dateValue}/>
<label>
Event Time
</label>
<TimePicker onChange={onChangeTime} value={timeValue} />
<label>
Event Description
</label>
<Input
name={"eventTitle"}
placeholder={"Event Title"}
type={"text"}
onChange={onChange}
/>
<label>
Event Description
</label>
<Input
name={"eventDescription"}
placeholder={"Event Description"}
type={"text"}
width={"300px"}
height={"300px"}
onChange={onChange}
/>
<Input
name={"submit"}
type={"submit"}
value={"Create"}
/>
</form>
</>
);
}
export default EventForm;`
The formData state variable will not update immediately, your console.log will always print the original value before the update. Also when the next state is computed using the previous state like in your example, you should use the functional update version of setState:
const [formData, setFormData] = useState({
firstName: '',
lastName: '',
contactEmail: '',
eventTitle: '',
eventDescription: '',
})
function onChange (e) {
let name = e.target.name;
let value = e.target.value;
setFormData((currentFormData) => {
const nextFormData = {
...currentFormData,
[name]: value,
})
console.log(nextFormData)
return nextFormData;
);
}

How to stop the page from refreshing and from loosing the users input on an unssucceful post request

I am working on a Merin Stack where a user can make a comment on a Program, and i am also using Google-react-Recaptcha to prevent spamming.
Everything is working well, except when a user forgets to declare that they are not a robot(to check the Recaptcha box) and the post request becomes unsuccessful. what happens is that the input that the user typed clears and it seems that the page is refreshing on a failed post request.
How do I make the user's inputs not clear from the field on a failed post request?
Here is my onSubmit function
const [error, setError] = useState("");
const [token, setToken] = useState("");
const reCaptcha = useRef();
const onSubmit = useCallback((e) => {
if (!token) {
alert("Yoou must verify the captcha");
setError("Yoou must verify the captcha");
}
setError("");
e.preventDefault();
setName("");
setDescription("");
axios
.post(
"http://localhost:9000/programs/" +
props.match.params.id +
"/programcomment",
{ name: name, description: eventDescription, token }
)
.then(function (response) {
onPageLoad();
alert("Submitted Succefully");
})
.catch(function (err) {
setError(err);
console.log(err);
})
.finally(() => {
reCaptcha.current.reset();
setToken("");
});
});
and my form inputs
<div className="container">
<div className="row " />
<div className="col-sm-2"></div>
<div className="col-sm-10"></div>
<div className="row">
<div className="col-sm-2" />
<div className="col-sm-10">
<form className="form" onSubmit={onSubmit}>
<div className="form-group">
<label htmlFor="name">Name:</label>
<input
type="text"
className="form-control"
id="name"
value={name}
required
onChange={handleChange("name")}
/>
<br />
<label htmlFor="comment">Comment:</label>
<textarea
className="form-control"
rows={5}
id="comment"
required
defaultValue={""}
value={eventDescription}
onChange={handleChange("description")}
/>
<br />
</div>
<ReCAPTCHA
ref={reCaptcha}
sitekey="6LecT-sZgfgrrtrtrtrtqQuMSJnMbxrif0ArqJqk2"
onChange={(token) => setToken(token)}
onExpired={(e) => setToken("")}
/>
<button
type="submit"
id="myBtn"
class="btn btn-success"
// onClick={handleSubscribe}
>
Submit
</button>
</form>
<p id="warning" />
</div>
</div>
Use an else section and move preventdefault to beginning.
const onSubmit = useCallback((e) => {
e.preventDefault();
if (!token) {
alert("Yoou must verify the captcha");
setError("Yoou must verify the captcha");
}
else{
setError("");
setName("");
setDescription("");
axios
.post(
"http://localhost:9000/programs/" +
props.match.params.id +
"/programcomment",
{ name: name, description: eventDescription, token }
)
.then(function (response) {
onPageLoad();
alert("Submitted Succefully");
})
.catch(function (err) {
setError(err);
console.log(err);
})
.finally(() => {
reCaptcha.current.reset();
setToken("");
});
}
});
Add e.preventDefault(); to your onSubmit callback and wrap to else block code which is invoked after checking token:
const onSubmit = useCallback((e) => {
e.preventDefault();
if (!token) {
alert("Yoou must verify the captcha");
setError("Yoou must verify the captcha");
} else {
setError("");
e.preventDefault();
setName("");
setDescription("");
axios
.post(
"http://localhost:9000/programs/" +
props.match.params.id +
"/programcomment",
{ name: name, description: eventDescription, token }
)
.then(function (response) {
onPageLoad();
alert("Submitted Succefully");
})
.catch(function (err) {
setError(err);
console.log(err);
})
.finally(() => {
reCaptcha.current.reset();
setToken("");
});
}
});
Use e.preventDefault at the beginning of your onSubmit function maybe ?
const onSubmit = useCallback((e) => {
e.preventDefault();

How can I edit form json data before submitting a form?

Posting a React form is typically straightforward. However, I need to customize the payload before sending it to this particular endpoint. I need it to look like this:
{
"httpMethod": "POST",
"body": {
"TableName": "Users",
"Item": {
"email": "sasquatch#bigfoot.com",
"first_name": "Sasquatch",
"last_name": "Bigfoot"
}
}
This is what I have now, but the format isn't correct:
const CreateUser = () => {
const [user, setUser] = useState({
'httpMethod': 'POST',
'body': {
'TableName' : 'Users',
'Item' : {
email: '', first_name: '', last_name: ''
}
}
});
const handleChange = (event) => {
setUser({...user, [event.target.name]: event.target.value})
}
const url = 'https://aaaaaaa.execute-api.us-east-1.amazonaws.com/dev/';
const handleSubmit = (e) => {
e.preventDefault()
axios.post(url, user)
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
})
}
return (
<div className="container">
<form className='white' onSubmit={handleSubmit}>
<h5 className="grey-text.text-darken-3">Create User</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="text" name="email" value={setUser.email} onChange={handleChange} required />
</div>
<div className="input-field">
<label htmlFor="first_name">First Name</label>
<input type="text" name="first_name" value={setUser.first_name} onChange={handleChange} required />
</div>
<div className="input-field">
<label htmlFor="last_name">Last Name</label>
<input type="text" name="last_name" value={setUser.last_name} onChange={handleChange} required />
</div>
<div className="input-field">
<button className="btn blue darken-3" type="submit">Sign Up</button>
</div>
</form>
</div>
);
}
When I find the data in the debugger it looks like this:
{
"httpMethod":"POST",
"body": {
"TableName":"Users",
"Item": {
“email":"",
"first_name":"",
"last_name":""
}
},
"email":"sasquatch#bigfoot.com",
"first_name":"Sasquatch",
"last_name":"Bigfoot"}
Maybe this is completely the wrong way of going about this? I'm open to making this work or going a different and more effective route.
On change , set the event name and value to user.body.Item not on user
const handleChange = (event) => {
setUser({...user, user.body.Item[event.target.name]: event.target.value})
}
You could try this to stitch the payload together:
const handleSubmit = (e) => {
var payload = {
httpMethod: "POST",
body: {
TableName: "Users",
Item: {
email: user.email,
first_name: user.first_name,
last_name: user.last_name
}
}
e.preventDefault()
axios.post(url, payload)
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
})
}

Problem with fetching API with user input

I'm building a search form where you can search for a city/country. I'm getting a response, but it adds localhost to the url
http://localhost:3000/api.geonames.org/searchJSON?q=london&username=username
Which it shouldn't do... What I'm I doing wrong?
state = {
text: ""
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value
})
}
componentDidMount() {
const endpoint = `${api}q=${this.state.text}&username=${userName}`
console.log(endpoint)
fetch(endpoint)
.then(res => {
console.log(res)
})
}
handleSubmit = (e) => {
e.preventDefault()
this.setState({text: ""})
this.componentDidMount()
}
render() {
return (
<div>
<h1>CityPop</h1>
<form onSubmit={this.handleSubmit}>
<h3>Search by city</h3>
<input
type="search"
name="text"
value={this.state.text}
onChange={this.handleChange}
/>
<button>Search city</button>
</form>
</div>
)
}
Just add http/https protocol before the link:
const endpoint = `https://${api}q=${this.state.text}&username=${userName}`;

Resources