React-dates: isDayBlocked fails to block day until blur'd and refocused

Created on 18 Nov 2017  路  10Comments  路  Source: airbnb/react-dates

react: 16.1.1
react-dom: 16.1.1
react-dates: 15.1.0

My component is initialized as follows:

<SingleDatePicker
    id="delivery_date"
    hideKeyboardShortcutsPanel
    placeholder="Date"
    isDayBlocked={this.isDayBlocked.bind(this)}
    numberOfMonths={1}
    date={this.state.date}
    focused={this.state.dateFocused}
    onDateChange={this.onDateChange.bind(this)}
    onFocusChange={this.onFocusChange.bind(this)}
/>

My isDayBlocked method looks like this:

isDayBlocked(day: Moment): boolean {
    let mock = moment().add(6, 'days').startOf('day')
    if(day.isSame(mock)) {
        return true;
    }
    return false;
}

The result I am seeing is as follows. The day (6 days from now) is not blocked when the calendar opens. However, if I blur the input field and then refocus it, you can see that the "blocked" date renders with the blocked style. There is a catch though, I can still select the blocked date.

In the example below you can see that when the calendar open's the 23rd of November is not blocked. Blurring a refocusing the input field however causes it to draw properly.

react-dates-issue

^ example showing the focus->blur->focus behavior

If I change my isDayBlocked to just be return true Upon focusing on the calendar's input field it opens with all days blocked and non-clickable.

I am using all of the default styles. The only thing I can currently think of is this is being rendered by Hypernova so maybe that has something to do with it?

Though if I do something contrived like this:

let datePicker = null;
let isServer = true;

try{
    window
    isServer = false;
} catch(_){}

if(!isServer){
    datePicker = <SingleDatePicker
        id="delivery_date"
        hideKeyboardShortcutsPanel
        placeholder="Date"
        isDayBlocked={this.isDayBlocked.bind(this)}
        numberOfMonths={1}
        date={this.state.date}
        focused={this.state.dateFocused}
        onDateChange={this.onDateChange.bind(this)}
        onFocusChange={this.onFocusChange.bind(this)}
    />
}

... later...
{datePicker}

Then it still exhibits the same behavior.

Most helpful comment

For me it was that I forgot to specify the comparison granularity for moment:

// before
  isDayBlocked(day) {
    const { unavailableDays } = this.props;
    return unavailableDays.some((unavailableDay) => moment(unavailableDay).isSame(day));
  }

// after
  isDayBlocked(day) {
    const { unavailableDays } = this.props;
    return unavailableDays.some((unavailableDay) => moment(unavailableDay).isSame(day, 'day'));
  }

All 10 comments

Did you figure it out?

Ya, I鈥檓 good

@aventurella how did you solve this? Experiencing the same behaviour myself.

For me it was that I forgot to specify the comparison granularity for moment:

// before
  isDayBlocked(day) {
    const { unavailableDays } = this.props;
    return unavailableDays.some((unavailableDay) => moment(unavailableDay).isSame(day));
  }

// after
  isDayBlocked(day) {
    const { unavailableDays } = this.props;
    return unavailableDays.some((unavailableDay) => moment(unavailableDay).isSame(day, 'day'));
  }

@thomassnielsen hi, have the same problem, but granularity doesn't solve it. Maybe there were other issues along with this one, that you solved to make it work? @aventurella

We didn't change anything else, the code above is how we run it in production.

so the solution for me was to change
isDayBlocked={this.isDayBlocked} to isDayBlocked={(day) => this.isDayBlocked(day)}

@nazartry That makes sense as the latter forces a recalculation on every render.

If you are having trouble with performance as a result, it may be beneficial to have a class method like isDayBlockedFactory that creates a new isDayBlocked method only when you need it to be recalculated. :)

@thomassnielsen we also ship a isSameDay method with react-dates that's useful for this situation (and we've found to be a bit faster than the built in moment method). :) Glad you solved your issue!

@majapw cool! thanks for mentioning that, it will be super beneficial in my case

@nazartry That makes sense as the latter forces a recalculation on every render.

This solved my issue. I didn't know about this behaviour.

Was this page helpful?
0 / 5 - 0 ratings