React-date-picker: In Gatsby, in Firefox, all click events close calendar

Created on 5 Jun 2020  路  9Comments  路  Source: wojtekmaj/react-date-picker

When react-date-picker is used in a Gatsby app within a Firefox browser all click events (whether on the calendar days or the navigation arrows at the top) all close the calendar instantly. When I click on a day, the calendar closes without inputting a date. All click events seem to trigger react-date-picker--open class to change to react-date-picker--closed before anything else can happen.

To reproduce, spin up a new gatsby project and drop the datepicker in anywhere. I did not see this problem with a create-react-app.

If I mount the react-date-picker component on the DOM via ReactDOM, this fixes the problem, but that doesn't seem like a good workaround in my use case.

bug

Most helpful comment

Adding disableEnforceFocus={true} to Material UI Dialog fixed it:

import { Dialog } from '@material-ui/core'

<Dialog disableEnforceFocus={true} ></Dialog>

All 9 comments

Sorry for the delay. Been super busy in commercial projects.

Found the reason. The reason is that we have a method, onOutsideClick.

https://github.com/wojtekmaj/react-date-picker/blob/e520a0b1afc4ee952321016472d5af8c15379d97/src/DatePicker.jsx#L53-L57

If the method detects a click outside React-Date-Picker's wrapper, it closes the calendar. The thing is, in Gatsby, clicking on the calendar causes focusin to be triggered on #gatsby-focus-wrapper element. This is detected as a focus event outside React-Date-Picker and thus is closing the calendar.

We could do this awful, _awful_ hack:

import React, { useEffect, useRef, useState } from "react"
import DatePicker from "react-date-picker"

import Layout from "../components/layout"

function MyApp() {
  const [value, onChange] = useState();
  const datePicker = useRef();

  useEffect(() => {
    if (!datePicker.current) {
      return;
    }

    // Replace DatePicker's onOutsideAction with our own that takes Gatsby's focus wrapper into account

    const _this = datePicker.current;

    _this.onOutsideAction = (event) => {
      if (
        _this.wrapper
        && !_this.wrapper.contains(event.target)
        // This is the line that fixes it
        && event.target.id !== 'gatsby-focus-wrapper'
      ) {
        _this.closeCalendar();
      }
    }
  });

  return (
    <DatePicker
      ref={datePicker}
      onChange={onChange}
      value={value}
    />
  );
};

export default MyApp;

When you're done vomiting, it should work just fine :D

https://github.com/wojtekmaj/react-date-picker/issues/15#issuecomment-681825167
The fix above didn't worked for me. I'm using v8.0.1

I suggest placing a breakpoint in line with event.target.id !== 'gatsby-focus-wrapper' and investigate what was broken b y the development environment you use. Perhaps Gatsby is not adding this ID anymore, or used a different one...

@wojtekmaj I'm no longer working on the project that was running into this bug. I think your fix worked, but I never finished up the PR there before moving onto other features. I gave them a link to this Issue in case they want to implement it themselves, but otherwise you could close this issue if you want.

@wojtekmaj on my end, setting the condition as event.target.id !== '' makes the calendar work without closing itself.
i'll be testing it further but it seems it's working fine this way.

@wojtekmaj The issue happens when the date picker is inside the MUI Dialog, this isn't related with gatsby. Check the demo below:
https://codesandbox.io/s/react-date-picker-forked-1ee7e?file=/index.js

You have the normal working date picker on the page, and then you have the date picker inside the MUI Dialog. Click the button, open the calendar, click on the "month" to select the month on the month view:
image
then click on any month to see the issue happening.

Any idea what is happening here?
image

Adding disableEnforceFocus={true} to Material UI Dialog fixed it:

import { Dialog } from '@material-ui/core'

<Dialog disableEnforceFocus={true} ></Dialog>

Facing a similar issue with a custom calendar implementation. Maybe a shouldCalendarClose optional prop that, given the event triggering the close, can return true/false to change the behavior?

Good idea, I think it's worth implementing.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

podlesny picture podlesny  路  7Comments

cavishek39 picture cavishek39  路  3Comments

bhldev picture bhldev  路  6Comments

baffleinc picture baffleinc  路  4Comments

FrontendLead picture FrontendLead  路  8Comments