17

I searched for a good datepicker in React using bootstrap style. But everything I found wasn't working well or was not up to date...

I'm working with React 15.0.2 and Boostrap 3.3.6

Does anyone know a good datepicker component?

Tom Dalton
  • 6,122
  • 24
  • 35
G. Frx
  • 2,350
  • 3
  • 19
  • 31

5 Answers5

52

If you are using react-bootstrap, you can add type="date" to <Form.Control>. More information at https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date.

But you should note that <input type="date"> is implemented differently by each browser!

import Form from "react-bootstrap/Form";
    
....
    
<Form.Control type="date" />

Without react-bootstrap

<input type="date" class="form-control" />
Janek Beck
  • 23
  • 5
ravthiru
  • 8,878
  • 2
  • 43
  • 52
3

I'm using react-bootstrap and noticed that the many npm packages are not working and/or not satisfying my design. So I wrote my own component with the only dependency on react-bootstrap/Button however you could change to regular html <button>.

DatePicker React Bootstrap

import { useState, useMemo } from 'react';
import Button from 'react-bootstrap/Button';

const weekDays = { nl: ['Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za', 'Zo'] };

const FollowUp = ({ selectedDate, onChange }) => {
  const [showDate, setShowDate] = useState(new Date(selectedDate));

  // first day of the month, CAREFULL: object will change by for loop!
  const firstDayThisMonth = new Date(showDate.getFullYear(), showDate.getMonth(), 1);
  // getDay sunday=0 and we monday=0
  const dayOfWeek = (firstDayThisMonth.getDay() + 6) % 7;
  // first day of next month
  const firstDayNextMonth = new Date(showDate.getFullYear(), showDate.getMonth() + 1, 1);

  // loop whole month and keep in memo to save 1ms per time
  const month = useMemo(() => {
    const m = [];
    for (let d = firstDayThisMonth; d < firstDayNextMonth; d.setDate(d.getDate() + 1)) {
      m.push(new Date(d));
    }
    return m;
  }, [showDate]);

  return (
    <div className="hl-followus">
      <div className="hl-month d-flex flex-wrap flex-row align-items-baseline justify-content-between px-3 pt-3 bg-primary text-light">
        {selectedDate.getFullYear()}
      </div>
      <div className="hl-month d-flex flex-wrap flex-row align-items-baseline justify-content-between px-3 pb-3 bg-primary text-white h2">
        {selectedDate.toLocaleString('nl-nl', {
          weekday: 'short',
          day: 'numeric',
          month: 'long',
        })}
      </div>
      <div className="hl-month d-flex flex-wrap flex-row align-items-baseline justify-content-between px-2 py-2">
        <Button
          onClick={() => setShowDate(new Date(showDate.setMonth(showDate.getMonth() - 1)))}
          className={`hl-day-button rounded-circle p-0 hl-bc1 border-white'}`}
          variant="light"
        >
          <i className="fas fa-chevron-left" />
        </Button>
        <div className="h5">
          {showDate.toLocaleString('nl-nl', { month: 'long', year: 'numeric' })}
        </div>
        <Button
          onClick={() => setShowDate(new Date(showDate.setMonth(showDate.getMonth() + 1)))}
          className="hl-day-button rounded-circle p-0 hl-bc0 border-0"
          variant="light"
        >
          <i className="fas fa-chevron-right" />
        </Button>
      </div>
      <div className="hl-month d-flex flex-wrap flex-row">
        {weekDays.nl.map((weekDay) => (
          <div key={weekDay} className="hl-day  d-flex justify-content-center">
            <small>{weekDay}</small>
          </div>
        ))}
      </div>
      <div className="hl-month d-flex flex-wrap flex-row  ">
        <div style={{ width: `${dayOfWeek * 14.28}%` }} />
        {month.map((day) => {
          const highlightSelectedDate =
            selectedDate &&
            selectedDate.getDate() === day.getDate() &&
            selectedDate.getMonth() === day.getMonth() &&
            selectedDate.getYear() === day.getYear();
          return (
            <div key={day} className="hl-day d-flex justify-content-center">
              <Button
                onClick={() => onChange(day)}
                className={`hl-day-button rounded-circle p-0 ${!highlightSelectedDate &&
                  'hl-bc0 border-0'}`}
                variant={highlightSelectedDate ? 'primary' : 'light'}
              >
                {day.getDate()}
              </Button>
            </div>
          );
        })}
      </div>
      <style jsx>
        {`
          .hl-month {
            width: 350px;
          }
          .hl-day {
            flex: 0 0 14.28%;
          }
          .hl-followus :global(.hl-day-button) {
            width: 36px;
            height: 36px;
          }
        `}
      </style>
    </div>
  );
};

export default FollowUp;
Bob Siefkes
  • 1,133
  • 9
  • 11
2

React bootstrap using type as date:

import Form from "react-bootstrap/Form"; import { useState } from "react";

export default function App() {
  const [date, setDate] = useState(new Date());
  return (
    <div className="App">
     
              <Form.Control
                type="date"
                name="datepic"
                placeholder="DateRange"
                value={date}
                onChange={(e) => setDate(e.target.value)}
              />
          
    </div>
  );
}
Priyanga Manivelan
  • 432
  • 1
  • 5
  • 14
1

I use react-bootstrap-datetimepicker that works well. Yet, it requires CSS addition in case you use bootswatch theme. Besides, It can require some z-index adjustments depending on where you display it. Otherwise it works just fine.

Damien Leroux
  • 11,177
  • 7
  • 43
  • 57
  • Hi, thanks for reply. I tried but I get some issues... First css seems not load, but I add a reference in my gulp.babel.js file. And second when I click in a date inside the datepicker somes erros are shown (Uncaught TypeError: t.isSame is not a function) (Uncaught Invariant Violation: performUpdateIfNecessary: Unexpected batch number (current 5, pending 4) Do you have an idea ? – G. Frx Jun 01 '16 at 07:32
  • [css](https://github.com/quri/react-bootstrap-datetimepicker/tree/master/css) must be included in your index.html and enclosed in a script tag – Damien Leroux Jun 01 '16 at 08:14
  • It may be an error with `moment` usages: http://stackoverflow.com/questions/28335803/issame-function-in-moment-js-or-date-validation . Did you use `moment`? – Damien Leroux Jun 01 '16 at 08:17
  • In my project css (for componants) must not be placed in index.html but referenced in gulp.babel.js. But anyway, thanks for your reply, I'll seek by myself. – G. Frx Jun 01 '16 at 08:23
  • Yes, I use Moment, I'll check on that – G. Frx Jun 01 '16 at 08:25
  • That's was a problem with moment, thanks :) There is just css problem left and it will be fix. Thank you for help – G. Frx Jun 01 '16 at 08:52
  • this didn't really work out of the box for me. using bootstrap form controls with type date and time works better IMHO. See other replies – Raph Feb 02 '22 at 15:01
0

Like ravthiru said react-bootstrap form controls with type "data" and "time" will be the easiest one to go for and wont require any additional packages.

I personally like react-date-range which is quite customizable.

A heavier, complete, customizable alternative is to use material-ui pickers
You can try them here

Raph
  • 326
  • 3
  • 15