0

I am trying to build a booking app using react and for some reason when the user changes the state it is not re rendering the correct amount in the UI.

If I console.log() the value of guests this is not going below 0 as wanted, however the UI is not displaying the correct amount. Any suggestions ?

import React, { useEffect, useState } from 'react';
import { Link, Route, Routes } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import HotelDetails from './hotelDetails'
import '../styles/searchBar.css';



let linkStyle = { textDecoration: "none", color: "black" };

const SearchBar = (props) => {

    const navigate = useNavigate()

    const todaysDate = new Date();
    let tomorrow = new Date(todaysDate);
    tomorrow = tomorrow.setDate(tomorrow.getDate() + 1);

    const [location, setLocation] = useState('');
    const [startDate, setStartDate] = useState(todaysDate); // set check in date to todays date
    const [endDate, setEndDate] = useState(tomorrow); // set check out date, default tomorrow
    const [guests, setGuests] = useState(0);

    const [properties, setProperties] = useState([]);

    // debug
    console.log('check in', startDate);
    console.log('check out', endDate);
    console.log('todays date', todaysDate);
    console.log('guests', guests);

    function handleCheckInDate(e) {
        setStartDate(e)
    }
    function handleCheckOutDate(e) {
        setEndDate(e)
    }


    useEffect(() => {
        fetch(`http://localhost:5000/hotels/${location}`).then((response) => {
            response.json().then((data) => {
                setProperties(data);
            })
        })
        if (guests <= 0) {
            setGuests(0);
            // It does not re render in the input field
        }
        if (endDate <= startDate) {
            alert('Please select a date after your check in date');
            setEndDate(tomorrow);
        }

    }, [location, startDate, endDate, setEndDate, setStartDate, guests, setGuests])




    return (
        <>
            <div className='bar'>
                <h2 className='subtitle'>Find your perfect stay...</h2>
                <div className='searchBar'>
                    <div className='field'>
                        <input type='text' className='input' placeholder='Where to ?' onChange={(e) => setLocation(e.target.value)} required />
                    </div>
                    <p>Check in</p>
                    <div className='field'>
                        {<input type='date' className='input' placeholder={todaysDate} onChange={(e) => /*setStartDate(e.target.value)*/ handleCheckInDate(e.target.value)} required />}
                    </div>
                    <p>Check out</p>
                    <div className='field'>
                        {<input type='date' className='input' placeholder={tomorrow} onChange={(e) => /* setEndDate(e.target.value)*/ handleCheckOutDate(e.target.value)} required />}
                    </div>
                    <div className='field'>
                        <input type='number' className='input' placeholder='Number of guests' onChange={(e) => setGuests(e.target.value)} required />
                    </div>

.....

1 Answers1

1

You're setting the state to reflect the input changes, but you also need to go the other way around - you need to configure the input to reflect the state. Otherwise, the state value isn't doing anything. You need

<input
  type='number'
  className='input'
  placeholder='Number of guests'
  onChange={(e) => setGuests(e.target.value)}
  value={guests}
  required
/>

But a better approach would be to use .valueAsNumber so that you set a number instead of a string to state, and to take the maximum of the current value and 0, instead of putting the logic in useEffect. You might also want to account for non-integer numbers.

<input
  type='number'
  className='input'
  placeholder='Number of guests'
  onChange={(e) => {
    // .valueAsNumber isn't strictly needed if calling Math.max here
    setGuests(Math.max(0, e.target.valueAsNumber));
  }}
  value={guests}
  required
/>
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320