acidb / mobiscroll

Cross platform UI controls for progressive web and hybrid apps (plain JS, jQuery, Angular and React)
https://mobiscroll.com
Other
1.54k stars 439 forks source link

Min prop causing infinite loop #486

Closed ntmk closed 3 years ago

ntmk commented 3 years ago

Barebones example

<Datepicker
  controls={["calendar"]}
  select="range"
  min={moment()}
  onChange={(e) => {
    if (!e.value.includes(null)) {
      this.setState({ startDate: e.value[0], endDate: e.value[1] });
    }
  }}
/>;

When starting the range at the first available date results in an infinite loop

andrasz commented 3 years ago

@ntmk Thanks for the example. Unfortunately I could not reproduce the infinite loop issue. Can you put together a simple app and share it, where the issue can be seen? A simple create-react-app project will do, with just the minimum reproduction code.

Thanks!

andrasz commented 3 years ago

@ntmk Looks like I found the problem. So here's what happens: when using the moment() function gives a timestamp for the min prop. When selecting the first available date the datepicker validates it assigns the same value as the current timestamp, which than goes to the state with your setState call. This triggers a re-render of the component, but in the next rendering the min prop gets another timestamp with a few milliseconds later. The Datepicker again validates the current selection and changes the value to meet the min prop, which then triggers another state change, and so on.

The simplest solution here is to give the min prop an exact timestamp, instead of a moving one with each render:

min={moment().startOf('day')}