So ive got a Booking component which returns a form which lets you choose number of Guests, Time, Occasion and a Date, but i need a way to lift the State up from this component so that i can use it in the future with an API.
I think i dont have the knowledge of the right Syntax or correct way of putting this component and its state. Ive been trying to Code it but the only thing i came up with is this:
import React from 'react'
import { useState } from 'react';
const availableTimes = [
{value: "17:00", text: "17:00"},
{value: "18:00", text: "18:00"},
{value: "19:00", text: "19:00"},
{value: "20:00", text: "20:00"},
{value: "21:00", text: "21:00"},
{value: "22:00", text: "22:00"},
]
const Guests = [
{value: "1", text: "1"},
{value: "2", text: "2"},
{value: "3", text: "3"},
{value: "4", text: "4"},
{value: "5", text: "5"},
{value: "6", text: "6"},
{value: "7", text: "7"},
{value: "8", text: "8"},
{value: "9", text: "9"},
]
const Occasion = [
{value: "Birthday", text: "Birthday"},
{value: "Anniversary", text: "Anniversary"},
]
const Select = ({value, options, onChange}) => {
return(
<select value={value} onChange={onChange}>
{options.map(option => {
return(<option key={option.value} value={option.value}>{option.text}</option>)
})}
</select>
)
}
const Bookingform = () => {
const[resdate, setResdate] = useState("");
const[guests, setGuests] = useState("");
const[occasion, setOccasion] =useState("");
const[restime, setRestime] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
const data = {
Reservation_Time: restime,
Occasion: occasion,
Guests: guests,
Reservation_Date: resdate
}
const json = JSON.stringify(data);
console.clear()
console.log(json)
setResdate("");
setRestime("");
setGuests("");
setOccasion("");
console.log("Form submitted!");
}
return (
<>
<div className='BookingForm'>
<form onSubmit={handleSubmit}>
<fieldset>
<div className='Field'>
<field>
<label htmlFor='res-date'>Choose Date</label>
<input id="res-date" type="date" placeholder='res-date' name='res-date' value={resdate} onChange={(e)=> setResdate(e.target.value)}/>
<label htmlFor='res-time'>Choose time:</label>
<Select id="restime" placeholder="restime" name="restime" value={restime} options={availableTimes} onChange={(e) => setRestime(e.target.value)} />
<label htmlFor="guests">Number of Guests</label>
<Select id="guests" placeholder='guests' name='guests' value={guests} options={Guests} onChange={(e) => setGuests(e.target.value)}/>
<label htmlFor="occasion">Occasion</label>
<Select id="occasion" placeholder='occasion' name="occasion" value={occasion} options={Occasion} onChange={(e) => setOccasion(e.target.value)}/>
</field>
</div>
<button type='submit'>Submit</button>
</fieldset>
</form>
</div>
</>
)
}
export default Bookingform
CodePudding user response:
I think you should read this article:
https://dev.to/smeijer/simple-form-handling-in-react-o72
But a better way than what you have written is using FormData
:
function MyForm() {
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
const values = Object.fromEntries(data.entries());
if (!Number(values.age)) {
alert('Your age must be a number');
return;
}
console.log('submitting', values);
};
return (
<form onSubmit={handleSubmit}>
<h1>Hi!</h1>
<p>Enter your name:</p>
<input type="text" name="username" />
<p>Enter your age:</p>
<input type="text" name="age" />
<br /><br />
<input type="submit" />
</form>
);
}
Obviously a much better way would be to create a Hook for yourself using FormData which you can see a full example of it in the article I mentioned above.
CodePudding user response:
So after some more research and reading the mentioned article i came up with this Solution. Is this a valid way of lifting the State of my Component to its Parent?
const formReducer= (state, event) => {
return {
...state,
[event.name]: event.value
}
}
const BookinForm = (props) => {
const [formData, setFormData] = useReducer(formReducer, {});
const [submitting, setSubmitting] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
setSubmitting(true);
props.onSubmit(formData);
setTimeout (() => {
setSubmitting(false);
}, 3000)
};
const handleChange = event => {
const isCheckbox = event.target.type === "checkbox";
setFormData({
name: event.target.name,
value: event.target.value,
value: isCheckbox ? event.target.checked : event.target.value,
});
}
return (
<div className="Wrapper">
<h1>Reserve a Table</h1>
{submitting && <div>You are submitting the following:
<ul>
{Object.entries(formData).map(([name, value]) => (
<li key={name}><strong>{name}</strong>:{value.toString()}</li>
))}
</ul>
</div> }
<form onSubmit={handleSubmit}>
<fieldset>
<label>
<p>Name</p>
<input name="name" onChange={handleChange}/>
</label>
<label>
<p>Email</p>
<input name="email" onChange={handleChange}/>
</label>
<label>
<p>Telephone</p>
<input name="telephone" onChange={handleChange}/>
</label>
</fieldset>
<fieldset>
<label>
<p>Time</p>
<select name="Time" onChange={handleChange}>
<option>17:00</option>
<option>18:00</option>
<option>19:00</option>
<option>20:00</option>
<option>21:00</option>
<option>22:00</option>
</select>
</label>
<label>
<p>Date</p>
<input type="date" name="Time" onChange={handleChange}/>
</label>
<label>
<p>Guests</p>
<input type="number" name="count" min="1" max="9" onChange={handleChange} step="1"/>
</label>
<label>
<p>Choose Occasion</p>
<select>
<option>Anniversary</option>
<option>Birthday</option>
</select>
</label>
</fieldset>
<button type="submit">Submit</button>
</form>
</div>
)
}
it does function as intended as i can Console log the Data from my Form inside my Parent component if i tell it to use this function On Submit:
const getData = (data) => {
console.log("Coming from Parent", data)
};
Any advice still here or does this code look fine for more experienced people?