React: capturing form values that were not changed - reactjs

In the tutorials I've found, the best way to capture forms inputs, is to use a "onchange" handler.
However, how should we deal with fields that are left to the default value ?
For example in something like the example below, if "country" is left to the default value, the "formData" will never get it.
const [formData, setFormData] = useReducer(formReducer, {});
const handleChange = event => {
setFormData({
name: event.target.name,
value: event.target.value,
});
}
const handleSubmit = event => {
event.preventDefault();
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
};
fetch('http://0.0.0.0:8000/add_user/', requestOptions)
}
<form onSubmit={handleSubmit}>
<fieldset>
<input type="text" name="name" placeholder="Name" onChange={handleChange} />
<input type="text" name="country" value="" onChange={handleChange} required />
</fieldset>
<Button type="submit">Submit</Button>
</form>
I've thought about some solutions but I don't think they are the best practices. For example, adding a snippet of code that manually assigns all default values to the form in the construction, so the formData is pre-filled.
Is there a clean & nice way to do it ?

In your useReducer hook you should store initial country value and then assign it to the value in country input, like below:
const [formData, setFormData] = useReducer(formReducer, { country: "" });
<form onSubmit={handleSubmit}>
<fieldset>
<input type="text" name="name" placeholder="Name" onChange={handleChange} />
<input type="text" name="country" value={formData.country} onChange={handleChange} required />
</fieldset>
<Button type="submit">Submit</Button>
</form>

Related

React How do I extract data from a form when triggering onSubmit event?

I am messing around with Riot's API that allows getting information of a player by the player's name. I am trying to get an API key (I only got a 24 hour key) and the target player's name from users' input.
export function PlayerSearch() {
function handlesubmit(e) {
console.log(e.target);
e.preventDefault();
}
return (
<div className='player'>
<div className='inputfield'>
<form onSubmit={handlesubmit} method='GET' autoComplete="off">
<div>
<label htmlFor="key">Your API key:</label>
<input
placeholder='Your API key'
onFocus={(e)=>{e.target.placeholder=''}}
type="text"
id="key"
name="key" />
</div>
<div>
<label htmlFor="name">Player name:</label>
<input
placeholder='Player name'
onFocus={(e)=>{e.target.placeholder=''}}
type="text"
id="name"
name="name" />
</div>
<div>
<input type='submit' />
</div>
</form>
</div>
</div>
);
}
And I got this in the console:
So how exactly do I extract the two inputs from the form?
In addition, is it possible that I can call another component and pass data as props to handle the submitted data so that the code is cleaner?
You should have a state to store your inputs:
const [formData, setFormData] = useState({ key: "", name: "" });
Then you need a function that gets called onChange of your input fields to update your state:
const onChange = (event) => {
setFormData({ ...formData, [event.target.name]: event.target.value });
};
And you need to pass that function to your input onChange property:
<input
placeholder="Your API key"
onFocus={(e) => {
e.target.placeholder = "";
}}
type="text"
name="key"
value={formData.key}
onChange={onChange}
/>
Then you can access the state in your handleSubmit:
function handlesubmit(e) {
console.log(formData);
e.preventDefault();
}

POST request sending an empty object even though console.log is show input values are being captured

When i submit the form, the object shows up as empty in my db.json file even though console.log is showing that i've capture the inputs.
There are no errors that are popping up, but rather once i hit post, it just shows a new object with an unique ID but nothing that was entered into the form was captured.
import React, { useState } from "react";
const blankNewLegend = {
name:"",
image:"",
nickname:"",
legendType:"",
tactAbility:"",
passAbility:"",
ultAbility:"",
season: 0,
likes: 0,
};
function NewLegendForm() {
const[newLegend, setNewLegend] = useState(blankNewLegend)
console.log(newLegend)
function handleChange(e){
console.log(e)
setNewLegend((prev) => ({
...prev,
[e.target.name] : e.target.value
}
));
e.preventDefault();
}
function handleSubmit(e){
e.preventDefault();
console.log(newLegend)
fetch('http://localhost:6004/legends',{
method: "POST",
header: {
"Content-Type": "application/json"
},
body: JSON.stringify(newLegend),
})
.then((res) => {
console.log(res, 'this')
})
}
return (
<div className="new-legend-form">
<h2>Add New Legend</h2>
<form onSubmit={handleSubmit} >
<input type="text" name="name" placeholder="Legend name" value={newLegend.name} onChange={handleChange}/>
<input type="text" name="image" placeholder="Image URL" value={newLegend.image} onChange={handleChange}/>
<input type="text" name="nickname" placeholder="Nickname" value={newLegend.nickname} onChange={handleChange}/>
<input type="text" name="legendType" placeholder="Legend Type" value={newLegend.legendType} onChange={handleChange}/>
<input type="text" name="tactAbility" placeholder="Tactical Ability" value={newLegend.tactAbility} onChange={handleChange}/>
<input type="text" name="passAbility" placeholder="Passive Ability" value={newLegend.passAbility} onChange={handleChange}/>
<input type="text" name="ultAbility" placeholder="Ultimate Ability" value={newLegend.ultAbility} onChange={handleChange}/>
<input type="number" name="season" placeholder="Debut Season" value={newLegend.season} onChange={handleChange}/>
<input type="number" name="likes" placeholder="Likes" value={newLegend.likes} onChange={handleChange}/>
<button type="submit">Add Legend</button>
</form>
<p>{newLegend.name}</p>
</div>
);
}
export default NewLegendForm;
Your database API can't read the content-type. In your fetch statement, change the key "header" to "headers" (i.e. plural), as shown below. You should then see the full json object in your db.json file:
function handleSubmit(e){
e.preventDefault();
console.log(newLegend)
fetch('http://localhost:6004/legends',{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(newLegend),
})
.then((res) => {
console.log(res, 'this')
})
}

How to create editable form inputs with existing prefill data in React

I have some data and form inputs, I need to prefill the existing data in the fields and when click on edit I like to edit the data and submit it to the state on button click
const data = {
name: "nazar",
email: "nazar#gmail.com",
phone: 123456789
};
const [ editData, setEditData ] = useState()
function handleEdit(){
}
function handleSubmit(){
}
<form onChange={handleEdit}>
<input type="text" name='name'/><button>Edit</button><br/>
<input type="text" name='email'/><button>Edit</button><br/>
<input type="text" name='phone'/><button>Edit</button><br/>
<button type='submit' onSubmit={handleSubmit}>Submit</button>
</form>
// declare your data as initial state
const [data, setData] = React.useState({
name: 'nazar',
email: 'nazar#gmail.com',
phone: 123456789,
});
// handle on change according to input name and setState
const handleChange = (e) => {
setData({ ...data, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault()
// take data to submit
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
name="name"
value={data.name} // inject state correspond to input and so on
onChange={handleChange}
/>
<button>Edit</button>
<br />
<input
type="text"
name="email"
value={data.email}
onChange={handleChange}
/>
<button>Edit</button>
<br />
<input
type="text"
name="phone"
value={data.phone}
onChange={handleChange}
/>
<button>Edit</button>
<br />
<button type="submit">
Submit
</button>
</form>
</div>
);

Formsubmit.co form not working in reactapp

I added formsubmit service to my email form on my react application simple personal website. but it does not seem to be working. It does nothing. Does the extra javascript in there mess with the formsubmit service? I actually put my real email in just changed it for this post.
import React, { useState } from 'react';
import './styles.contactform.css';
function ContactForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log(name, email, message)
setName('')
setEmail('')
setMessage('')
}
return (
<div className="contact-container">
<form className="contact-form" action="https://formsubmit.co/myemail#email.com" method="POST" onSubmit={handleSubmit}>
<input type="hidden" name="_next" value="https://notmicahclark.herokuapp.com/"/>
<input type="text" value={name} id="name" name="name" placeholder="Name..." onChange={(e) => setName(e.target.value)} required/>
<input type="email" value={email} id="email" name="email" placeholder="Email..." onChange={(e) => setEmail(e.target.value)} required/>
<img className="letter-img" src="contact_form_imagepng.png" alt="Mail Letter"/>
<input id="message" value={message} name="message" placeholder="Your message..." onChange={(e) => setMessage(e.target.value)}/>
<button type="submit" value="Submit">Submit</button>
</form>
</div>
);
}
export default ContactForm;
To overcome this issue, you can use the AJAX form feature provided by FormSubmit.
According to their documentation:
You can easily submit the form using AJAX without ever having your
users leave the page. — this even works cross-origin.
Please refer to their documentation about AJAX forms (sample code snippets are available): https://formsubmit.co/ajax-documentation
I've tested your code. The problem is that you are both using the form's HTML action field, and at the same time using your own method for form submission. Remove the action=... call and instead write this in your handleSubmit method.
fetch('https://formsubmit.co/ajax/myemail#email.com', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(Object.fromEntries(new FormData(event.target))),
})
Should work like a charm. Add then and catch statements to your liking.

How to add n number of emails in react?

I have created a user registration form which contains of firstname,lastname,email etc.
Here a user can add n number of emails.For this,I have created a button and onClick it should open the input field.
<--Here is the code -->
const [formData, setFormData] = useState({
firstname: "",
lastname: "",
email: "",
})
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const handleSubmit = async (e) => {
e.preventDefault();
const newStudent = {
firstname,
lastname,
email,
}
try {
const config = {
headers: {
"Content-Type": "application/json",
},
};
const body = JSON.stringify(newStudent);
await axios.post(`http://localhost:5000/student`, body, config);
}
const handleClick = () => {
return <Input type="email" name="email" value={email} onChange={handleChange} />
};
return (
<Form className={classes.root} onSubmit={handleSubmit}>
<div>
<Input
id="standard-multiline-flexible"
label="First Name"
multiline
name="firstname"
value={firstname}
onChange={handleChange}
/>
</div>
<div>
<Input
id="standard-multiline-flexible"
label="Last Name"
name="lastname"
value={lastname}
onChange={handleChange}
multiline
/>
</div>
<div>
<Input
id="standard-multiline-static"
type="email"
label="Email"
name="email"
onChange={handleChange}
value={email}
multiline
/>
<button className="btn btn-primary" onClick={handleClick}>
Add
</button>
<PrimaryButton>Submit</PrimaryButton>
</Form>
)
Can anyone tell me how should I define the handleClick() so that whenever I click the add button,it renders a new Input field?
Another way you could achieve this if you want the user to see their input emails remove them etc is to do the following:
Create an emails state array.
Add an email text field with an add button next to it.
When the user enters an email and presses add, add that email to the array.
You can then map the array to show the added emails as a list with the option to delete the emails if the user decides to.
At the end of handle click
Instead of doing this
return <Input type="email" name="email" value={email} onChange={handleChange} />
Do this ->
setFormData({firstname: "",lastname: "",email: ""});
Edits
You can display the emails via a list after making the API call
You can have a delete button to delete that email from the list.
"There are n ways to implement. Please be more specific"

Resources