So I’m having this project and it kills me with the way the instructions unfold step by step.
At first they asked me to create a BookingForm.js component that includes a form, for my app.
They asked me to use “useEffect” hook to manage the state in the component, and so did I.
Right after, they asked me to lift the state of specific element to another component, and pass the state down as props, to my BookingForm.js component.
And since I’m inexperienced with hooks and useReducer, I’m struggling so much to find the solution.
I feel I could make it work on my own, if it wasn’t for this shift from useState to useReducer, because I don’t know what to keep and what to change now.
This is my Main.js component that imports the BookingForm.js component and renders it.
import React, {useReducer} from 'react';
import ReactLogo from '../bruchetta.svg';
import image1 from '../greeksalad.jpg';
import image3 from '../lemondessert.jpg';
import image4 from '../restauranfood.jpg';
import image5 from '../customer1.jpg';
import image6 from '../customer2.jpg';
import image7 from '../customer3.jpg';
import image8 from '../customer4.jpg';
import image9 from '../restaurant.jpg';
import image10 from '../mario-and-adrian.jpg';
import { faStar } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom';
import BookingForm from './BookingForm';
function Main() {
function initializeTimes() {
return [
'17:00',
'18:00',
'19:00',
'20:00',
'21:00',
'22:00'
];
}
const [availableTimes, dispatch] = useReducer(updateTimes, initializeTimes());
const showBookingForm = false;
function updateTimes(state, action) {
switch (action.type) {
case 'update_times':
return action.availableTimes;
default:
return state;
}
}
return (
<div>
{showBookingForm && (<BookingForm availableTimes={availableTimes} dispatch={dispatch}/>)}
...rest of my Main code...
</div>
);
}
export default Main;
And this is my BookingForm.js component:
import React, { useState } from 'react';
function BookingForm({ availableTimes = [], dispatch }) {
const [date, setDate] = useState('');
const [time, setTime] = useState('17:00');
const [guests, setGuests] = useState(1);
const [occasion, setOccasion] = useState('Birthday');
const handleFormSubmit = (event) => {
event.preventDefault();
// Handle form submission logic here
// e.g., display form data or make an API call
console.log('Form submitted:', { date, time, guests, occasion });
};
const handleDateChange = (e) => {
const selectedDate = e.target.value;
setDate(selectedDate);
dispatch({type: "update_times"}); // Dispatch the selected date to update available times
};
return (
<form style={{ display: 'grid', maxWidth: '200px', gap: '20px' }} onSubmit={handleFormSubmit}>
<label htmlFor="res-date">Choose date</label>
<input type="date" id="res-date" value={date} onChange={handleDateChange} />
<label htmlFor="res-time">Choose time</label>
<select id="res-time" value={time} onChange={(e) => setTime(e.target.value)}>
{availableTimes.map((availableTime) => (
<option key={availableTime} value={availableTime}>
{availableTime}
</option>
))}
</select>
<label htmlFor="guests">Number of guests</label>
<input type="number" placeholder="1" min="1" max="10" id="guests" value={guests} onChange={(e) => setGuests(e.target.value)} />
<label htmlFor="occasion">Occasion</label>
<select id="occasion" value={occasion} onChange={(e) => setOccasion(e.target.value)}>
<option value="Birthday">Birthday</option>
<option value="Anniversary">Anniversary</option>
</select>
<input type="submit" value="Make Your reservation" />
</form>
);
}
export default BookingForm;
At first when the website loads, I initialize the ‘showBookingForm’ = ‘false’ in Main.js, so that this component will not be displayed, and will only appear when the user clicks on any of the respective links.
When that happens, the rest of the Main component disappears properly.
But when I’m in my BookingForm, and the user tries to pick a date, it throws either of the errors :
“dispatch is not a function / initializeTimes is not a function”
with whatever attempt I tried.
What I want is for these instructions to be met by, but I can’t:
“Step 1: Life state up to the Main component
As you added the table booking state to the BookingForm component in the previous exercise, in this exercise, you need to lift the state up to the Main component. This is the preferred approach in this case, as your app is relatively simple.
Move the availableTimes useState hook from the BookingForm component into the Main component
Pass down the state and state changing functions from the Main component to the BookingForm component using props in order to make state work across different components.
Step 2: Update BookingForm to display available times based on the selected date
The next step is to prepare the available times to be updated based on the date the user has selected. To do this, you will change the availableTimes state to a reducer.
In the Main component, create a function named updateTimes which will handle the state change. This function will change the availableTimes based on the selected date. For now, the function can return the same available times regardless of the date.
Next, create a function called initializeTimes which will create the initial state for the availableTimes.
Then, change availableTimes to a reducer using the useReducer function and provide the two previous functions as parameters.
Update the BookingForm component to dispatch the state change when the date form field is changed.
Tip: Include the newly selected date in the dispatch parameter.”