title: React function executes continuously and state keeps refreshing
body: <p>I have kind of a weird issue in React. I am using the Blitz JS framework along side with Prisma for database stuff.</p>
  <p>I have a function that queries the database for all entries from a date the user selects forward. It's used for a reservation system that I am trying to build.</p>
  <p>After I get the data I use it to create a <code>&lt;select&gt;</code> element and set as <code>&lt;option&gt;</code> every space that does not appear in the database. Everything works fine, the <code>&lt;select&gt;</code> and <code>&lt;option&gt;</code> display what they should, but as soon as I click the drop-down to see all available option, I think the state refreshes and the menu closes down.</p>
  <p>If I <code>console.log()</code> inside the function, it will go on forever in the console menu. Also in the terminal I can see the function being called about every second or so.</p>
  <p><a href="https://i.stack.imgur.com/vLveY.png" rel="nofollow noreferrer">terminal log</a></p>
  <p><a href="https://i.stack.imgur.com/XCLAX.png" rel="nofollow noreferrer">javascript console log</a></p>
  <p>I also tried querying the database from a <code>useEffect()</code> but <code>useEffect()</code> and <code>useQuery</code> (from Blitz.js) don't work together</p>
  <p>I will attach the code along side with comments for easier reading.</p>
  <p>Thank you for your time!</p>
  <p>Main page:</p>
  <pre><code>import { BlitzPage, invoke, useQuery } from &quot;blitz&quot;
  import { useState, useEffect, Suspense } from &quot;react&quot;
  import { UserInfo } from &quot;app/pages&quot;
  import DatePicker from &quot;react-datepicker&quot;
  import &quot;react-datepicker/dist/react-datepicker.css&quot;
  import addDays from &quot;date-fns/addDays&quot;
  import format from &quot;date-fns/format&quot;
  import insertBooking from &quot;app/bookings/mutations/insertBooking&quot;
  import getAllBookings from &quot;app/bookings/queries/getAllBookings&quot;
  import { useCurrentBookings } from &quot;app/bookings/hooks/useCurrentBookings&quot;
  import { useCurrentUser } from &quot;app/core/hooks/useCurrentUser&quot;
  
  const Add: BlitzPage = () =&gt; {
    //State for all options that will be added for the booking
    const [state, setState] = useState({
      intrare: 1,
      locParcare: 0,
      locPescuit: 0,
      casuta: 0,
      sezlong: 0,
      sedintaFoto: false,
      petrecerePrivata: false,
      totalPrice: 20,
    })
    //Date state added separately
    const [startDate, setStartDate] = useState(addDays(new Date(), 1))
  
    const [availableSpots, setAvailableSpots] = useState({
      pescuit: [0],
      casute: {},
      sezlonguri: {},
    })
  
    // The function that reads the DB, manipulates the data so I can have
    // an array of open spots and then renders those values in a select
    const PescuitSelect = () =&gt; {
      const totalFishingSpots = Array.from(Array(114).keys())
  
      const bookings = useCurrentBookings(startDate) //useCurrentBookings is a hook I created
  
      const availableFishingSpots = totalFishingSpots.filter(
        (o1) =&gt; !bookings.some((o2) =&gt; o1 === o2.loc_pescuit)
      )
      console.log(availableFishingSpots)
      setAvailableSpots({ ...availableSpots, pescuit: availableFishingSpots })
  
      return (
        &lt;select&gt;
          {availableSpots.pescuit.map((value) =&gt; {
            return (
              &lt;option value={value} key={value}&gt;
                {value}
              &lt;/option&gt;
            )
          })}
        &lt;/select&gt;
      )
    }
  
    // Date state handler
    const handleDate = (date) =&gt; {
      setStartDate(date)
    }
  
    // Update the price as soon as any of the options changed
    useEffect(() =&gt; {
      const totalPrice =
        state.intrare * 20 +
        state.locParcare * 5 +
        (state.casuta ? 100 : 0) +
        (state.locPescuit ? 50 : 0) +
        (state.sedintaFoto ? 100 : 0) +
        state.sezlong * 15
  
      setState({ ...state, totalPrice: totalPrice })
    }, [state])
  
    type booking = {
      starts_at: Date
      ends_at: Date
      intrare_complex: number
      loc_parcare: number
      loc_pescuit: number
      casuta: number
      sezlong: number
      sedinta_foto: boolean
      petrecere_privata: boolean
      total_price: number
    }
  
    // Here I handle the submit. &quot;petrecerePrivata&quot; means a private party. If that is checked
    // it does something, if not, something else
    function handleSubmit(event) {
      event.preventDefault()
      if (state.petrecerePrivata === true) {
        setState({
          ...state,
          intrare: 0,
          locParcare: 0,
          locPescuit: 0,
          casuta: 0,
          sezlong: 0,
          sedintaFoto: false,
          totalPrice: 100,
        })
      } else {
        const booking: booking = {
          starts_at: startDate,
          ends_at: addDays(startDate, 1),
          intrare_complex: state.intrare,
          loc_parcare: state.locParcare,
          loc_pescuit: state.locPescuit,
          casuta: state.casuta,
          sezlong: state.sezlong,
          sedinta_foto: state.sedintaFoto,
          petrecere_privata: state.petrecerePrivata,
          total_price: state.totalPrice,
        }
  
        invoke(insertBooking, booking) // Insert the new created booking into the database
      }
    }
  
    // State handler for everything but the price, that updates in the useEffect
    const handleChange = (evt) =&gt; {
      const name = evt.target.name
      const value = evt.target.type === &quot;checkbox&quot; ? evt.target.checked : evt.target.value
      setState({
        ...state,
        [name]: value,
      })
    }
  
    return (
      &lt;&gt;
        &lt;Suspense fallback=&quot;Loading...&quot;&gt;
          &lt;UserInfo /&gt;
        &lt;/Suspense&gt;
  
        {
          // Here starts the actual page itself
        }
  
        &lt;div className=&quot;mx-auto max-w-xs &quot;&gt;
          &lt;div className=&quot;my-10 p-4 max-w-sm bg-white rounded-lg border border-gray-200 shadow-md sm:p-6 lg:p-8 dark:bg-gray-800 dark:border-gray-700&quot;&gt;
            &lt;form className=&quot;space-y-6&quot; action=&quot;#&quot; onSubmit={handleSubmit}&gt;
              &lt;h5 className=&quot;text-xl font-medium text-gray-900 dark:text-white&quot;&gt;
                Fa o rezervare noua
              &lt;/h5&gt;
              {state.petrecerePrivata ? (
                &lt;&gt;
                  &lt;div&gt;
                    &lt;label
                      htmlFor=&quot;date&quot;
                      className=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300&quot;
                    &gt;
                      Alege Data
                    &lt;/label&gt;
                    &lt;div className=&quot;border-2 rounded&quot;&gt;
                      &lt;DatePicker
                        selected={startDate}
                        onChange={(date) =&gt; handleDate(date)}
                        dateFormat=&quot;dd/MM/yyyy&quot;
                        includeDateIntervals={[{ start: new Date(), end: addDays(new Date(), 30) }]}
                        className=&quot;cursor-pointer p-2&quot;
                      /&gt;
                    &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;label
                    htmlFor=&quot;checked-toggle&quot;
                    className=&quot;relative inline-flex items-center mb-4 cursor-pointer&quot;
                  &gt;
                    &lt;input
                      type=&quot;checkbox&quot;
                      name=&quot;petrecerePrivata&quot;
                      id=&quot;checked-toggle&quot;
                      className=&quot;sr-only peer&quot;
                      checked={state.petrecerePrivata}
                      onChange={handleChange}
                    /&gt;
  
                    &lt;div className=&quot;w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600&quot;&gt;&lt;/div&gt;
                    &lt;span className=&quot;ml-3 text-sm font-medium text-gray-900 dark:text-gray-300&quot;&gt;
                      Petrecere Privata
                    &lt;/span&gt;
                  &lt;/label&gt;
                &lt;/&gt;
              ) : (
                &lt;&gt;
                  &lt;div&gt;
                    &lt;label
                      htmlFor=&quot;date&quot;
                      className=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300&quot;
                    &gt;
                      Alege Data
                    &lt;/label&gt;
                    &lt;div className=&quot;border-2 rounded&quot;&gt;
                      &lt;DatePicker
                        selected={startDate}
                        onChange={(date) =&gt; setStartDate(date)}
                        dateFormat=&quot;dd/MM/yyyy&quot;
                        includeDateIntervals={[{ start: new Date(), end: addDays(new Date(), 30) }]}
                        className=&quot;cursor-pointer p-2&quot;
                      /&gt;
                    &lt;/div&gt;
                  &lt;/div&gt;
                  &lt;div&gt;
                    &lt;label
                      htmlFor=&quot;intrare&quot;
                      className=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300&quot;
                    &gt;
                      Bilete Intrare Complex
                    &lt;/label&gt;
                    &lt;input
                      type=&quot;number&quot;
                      name=&quot;intrare&quot;
                      id=&quot;intrare&quot;
                      placeholder=&quot;1&quot;
                      value={state.intrare}
                      onChange={handleChange}
                      className=&quot;bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white&quot;
                      required
                    /&gt;
                  &lt;/div&gt;
                  &lt;div&gt;
                    &lt;label
                      htmlFor=&quot;loParcare&quot;
                      className=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300&quot;
                    &gt;
                      Numar Locuri de Parcare
                    &lt;/label&gt;
                    &lt;input
                      type=&quot;number&quot;
                      name=&quot;locParcare&quot;
                      id=&quot;locParcare&quot;
                      placeholder=&quot;0&quot;
                      min=&quot;0&quot;
                      value={state.locParcare}
                      onChange={handleChange}
                      className=&quot;bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white&quot;
                    /&gt;
                  &lt;/div&gt;
  
                  &lt;div&gt;
                    &lt;label
                      htmlFor=&quot;locPescuit&quot;
                      className=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300&quot;
                    &gt;
                      Alege Locul de Pescuit
                    &lt;/label&gt;
  
                    {
                      // Here I call that function inside a Suspense and things go south
                    }
                    &lt;Suspense fallback=&quot;Cautam locurile de pescuit&quot;&gt;
                      &lt;PescuitSelect /&gt;
                    &lt;/Suspense&gt;
                  &lt;/div&gt;
  
                  &lt;div&gt;
                    &lt;label
                      htmlFor=&quot;casuta&quot;
                      className=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300&quot;
                    &gt;
                      Alege Casuta
                    &lt;/label&gt;
                    &lt;input
                      type=&quot;number&quot;
                      name=&quot;casuta&quot;
                      id=&quot;casuta&quot;
                      placeholder=&quot;0&quot;
                      min=&quot;0&quot;
                      max=&quot;18&quot;
                      value={state.casuta}
                      onChange={handleChange}
                      className=&quot;bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white&quot;
                    /&gt;
                  &lt;/div&gt;
                  &lt;div&gt;
                    &lt;label
                      htmlFor=&quot;sezlong&quot;
                      className=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300&quot;
                    &gt;
                      Alege Sezlong
                    &lt;/label&gt;
                    &lt;input
                      type=&quot;number&quot;
                      name=&quot;sezlong&quot;
                      id=&quot;sezlong&quot;
                      placeholder=&quot;0&quot;
                      min=&quot;0&quot;
                      max=&quot;21&quot;
                      value={state.sezlong}
                      onChange={handleChange}
                      className=&quot;bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white&quot;
                    /&gt;
                  &lt;/div&gt;
                  &lt;label
                    htmlFor=&quot;sedintaFoto&quot;
                    className=&quot;relative inline-flex items-center mb-4 cursor-pointer&quot;
                  &gt;
                    &lt;input
                      type=&quot;checkbox&quot;
                      name=&quot;sedintaFoto&quot;
                      id=&quot;sedintaFoto&quot;
                      className=&quot;sr-only peer&quot;
                      checked={state.sedintaFoto}
                      onChange={handleChange}
                    /&gt;
  
                    &lt;div className=&quot;w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600&quot;&gt;&lt;/div&gt;
                    &lt;span className=&quot;ml-3 text-sm font-medium text-gray-900 dark:text-gray-300&quot;&gt;
                      Sedinta foto
                    &lt;/span&gt;
                  &lt;/label&gt;
                  &lt;label
                    htmlFor=&quot;petrecerePrivata&quot;
                    className=&quot;relative inline-flex items-center mb-4 cursor-pointer&quot;
                  &gt;
                    &lt;input
                      type=&quot;checkbox&quot;
                      name=&quot;petrecerePrivata&quot;
                      id=&quot;petrecerePrivata&quot;
                      className=&quot;sr-only peer&quot;
                      checked={state.petrecerePrivata}
                      onChange={handleChange}
                    /&gt;
  
                    &lt;div className=&quot;w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600&quot;&gt;&lt;/div&gt;
                    &lt;span className=&quot;ml-3 text-sm font-medium text-gray-900 dark:text-gray-300&quot;&gt;
                      Petrecere Privata
                    &lt;/span&gt;
                  &lt;/label&gt;
                &lt;/&gt;
              )}
  
              &lt;button
                type=&quot;submit&quot;
                className=&quot;w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800&quot;
              &gt;
                Subimt
              &lt;/button&gt;
            &lt;/form&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/&gt;
    )
  }
  export default Add
  </code></pre>
  <p><code>useCurrentBookings</code> hook:</p>
  <pre><code>import { useQuery } from &quot;blitz&quot;
  import getAllBookings from &quot;../queries/getAllBookings&quot;
  import format from &quot;date-fns/format&quot;
  
  export const useCurrentBookings = (startDate) =&gt; {
    const [booking] = useQuery(getAllBookings, format(startDate, &quot;yyyy-MM-dd&quot;)) // Here I query the database
    return booking
  }
  </code></pre>
  <p>Actual call to the database:</p>
  <pre><code>import db from &quot;db&quot;
  
  //And this is the actual call to the database
  export default async function getAllBookings(startsAt: string) {
    return await db.booking.findMany({
      where: { starts_at: { gte: new Date(startsAt) } },
    })
  }
  </code></pre>