简体   繁体   中英

Im a React Beginner and need to know how to Lift up State from my form

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

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.

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM