# Create a simple Date Range Picker in React.
Tags: react, webdev, reactdaterange, beginners
Published: 2023-05-26 04:00:00

[video](https://www.loom.com/share/a9fe99bd0062435c931148b1374a0676)

<figure>
  <iframe src="https://www.loom.com/share/a9fe99bd0062435c931148b1374a0676" frameborder="0" allowfullscreen="true" style="width:100%" height='300'> </iframe>
</figure>

Instantiate a new project

`$ npm create vite@latest`

Configure the app with the following:-

Project name: calendar-app

Framework: React

Variant: JavaScript

```

$ cd calendar-app

$ npm install

$ npm run dev

# to start the development server 
#open the development server in your browser
# mine is at http://localhost:5173/

```
> Open your newly created app in your preferred editor.
> For vs-code users in the project directory run `$ code .` it will open your application in vs-code.
  Remove all unneccasary files from the scaffolded project and your project should look like the screenshot below

```
#app.js

import './App.css'

  

function App() {

  return <>welcome</>

}

export default App
```
![first-screen](https://res.cloudinary.com/diggungrj/image/upload/v1685043688/calendar-app/first_screen_cqcwzf.png)

For our project we will be making use of the <strong>  react-date-range package </strong>

from your <i>  app/directory </i> run

`npm i react-date-range` [react-date-range](https://github.com/hypeserver/react-date-range)

this will add the package to your app dependencies.

we would also be using the date-fns package so

from your terminal again run

`npm install date-fns` [date-fns](https://date-fns.org/)

Inside your `/src` directory create a folder called _components_, inside the _components_ folder, create an empty file `singleCalendar.jsx`, you can do all these from the bash terminal.

```
$ cd src && mkdir components
$ cd components && touch singleCalendar.jsx

```
open the new file `singleCalendar.jsx` and import the `<DateRange />` component

```
import { DateRange } from 'react-date-range'

export const SingleCalendar = () => {

  return (

    <div>

      <DateRange />

    </div>

  )

}
```
then import the <i> SingleCalandar </i> into `App.jsx` your code should look like this
```
import './App.css'

import { SingleCalendar } from './components/singleCalendar'

function App() {
  return (
    <div>
      <SingleCalendar />
    </div>
  )
}

export default App

```
Next, we would import css from 'react-date-range' for styling. Add the following code to your `main.jsx` file
```
import 'react-date-range/dist/styles.css'
import 'react-date-range/dist/theme/default.css'
```
> You can remove all the default styling that comes with Vite.
> 
> When you are importing styles for a component, you should put the styles in the topmost component, so that you can use the same styles across other places in your app.

Your `main.jsx` should look like this

```

import React from 'react'

import ReactDOM from 'react-dom/client'

import App from './App.jsx'

import './index.css'

//Add styles for the calendar app

import 'react-date-range/dist/styles.css' // main style file
import 'react-date-range/dist/theme/default.css'

ReactDOM.createRoot(document.getElementById('root')).render(

  <React.StrictMode>

    <App />

  </React.StrictMode>

)

```
![https://res.cloudinary.com/diggungrj/image/upload/v1683865345/calendar-initial_oyjmxj.png](https://res.cloudinary.com/diggungrj/image/upload/v1683865345/calendar-initial_oyjmxj.png)

Good job getting here so far :clap:

Let's add a container where our calendar result will be viewed, we would be using an input element to store the calendar value.

```

import { DateRange } from 'react-date-range'

export const SingleCalendar = () => {

  return (

 <div className='container'>

      <DateRange className='calendarStyle' />

      <div>

        <input type='text' className='single-calendar-input' />

      </div>

    </div>

  )

}

```

![https://res.cloudinary.com/diggungrj/image/upload/v1683865344/calendar-input-initial_fihtyd.png](https://res.cloudinary.com/diggungrj/image/upload/v1683865344/calendar-input-initial_fihtyd.png)

Then let us style the input container,
- create a calendar icon
- style the input container

> create a <i> calendaricon </i> file and the add the following jsx to the file.
> _I copied this code from [heroicons](https://heroicons.com/)_

```
export const CalendarIcon = () => {
  return (
    <svg
      xmlns='http://www.w3.org/2000/svg'
      fill='none'
      viewBox='0 0 24 24'
      strokeWidth={1.5}
      stroke='currentColor'
      className='w-6 h-6'
    >
      <path
        strokeLinecap='round'
        strokeLinejoin='round'
        d='M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z'
      />
    </svg>
  )
}

```
next, add the css style  
> <i> note: I have included some classes in the styles for some elements that have not been created  yet.</i>
```

#  index.css

*,
*::after,
*::before {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 62.5%;
}

.wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
}

.container {
  padding: 5rem;
}

.calendarStyle {
  border: 1px solid #eee;
  font-family: poppins;
  border-radius: 1.5rem;
  z-index: 999;
  position: relative;
  background-color: #fff;
}

.icon {
  height: 1.6rem;
  width: 2rem;
}

input {
  height: 100%;
  width: 90%;
  border: none;
  outline: none;
}

.single-calendar-input {
  height: 4rem;
  width: 35rem;
  border-radius: 0.5rem;
  border: 1px solid #ddd;
  padding: 0 10px;
  font-weight: 500;
  color: #686868;
  margin-bottom: 1rem;
  display: flex;
  align-items: center;
}

.element-container {
  position: relative;
}

.dropdown {
  position: absolute;
  top: 50px;
  left: 0px;
}

.dropdown.active {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: 500ms ease;
}

.dropdown.inactive {
  opacity: 0;
  visibility: hidden;
  transform: translateY(-20px);
  transition: 500ms ease;
}

```
And also update the singleCalendar component,
```
import { DateRange } from 'react-date-range'
import { CalendarIcon } from '../assets/calendaricon'

export const SingleCalendar = () => {
  return (
 <div className='container'>
      <div>
        <div className='single-calendar-input'>
          <input type='text' />
          <div className='icon'>
            <CalendarIcon />
          </div>
        </div>
      </div>
      <DateRange className='calendarStyle' />   
    </div>
  )
}
```
Your page should look like this now

Nice job so far :thumbsup:
![screen2](https://res.cloudinary.com/diggungrj/image/upload/v1685046450/calendar-app/screen2_k5tffu.png)

## Let's start working on the functionalities

-   we handle the calendar value with useState
-   we will handle the date format
-   we will set an event listener on the input to open the calendar when clicked
-   we will close the calendar when any part of our page is clicked apart from the calendar component

### Handle the calendar state

```

# singleCalendar.jsx

import { useState } from 'react'

import { DateRange } from 'react-date-range'

import { CalendarIcon } from '../assets/calendaricon'

  
export const SingleCalendar = () => {

  const [state, setState] = useState([

    {

      startDate: new Date(),

      endDate: new Date(),

      key: 'selection',

    },

  ])

  
  return (

    <div className='container'>

      <DateRange

        className='calendarStyle'

        onChange={(item) => setState([item.selection])}

        ranges={state}

        showSelectionPreview={false}

        editableDateInputs={false}

        showMonthAndYearPickers={false}

        showDateDisplay={false}

        rangeColors={['#4C988E', '#4C988E', '#000000']}

        direction='horizontal'

      />

      <div className='single-calendar-input'>

        <input type='text' />

        <div className='icon'>

          <CalendarIcon />

        </div>

      </div>

    </div>

  )

}

```
if you `console.log({state})` you will see an array of your current selected date range.

![screen-3](https://res.cloudinary.com/diggungrj/image/upload/v1685048372/calendar-app/screen-3_v0awhh.png)

### Next, we will set an event listener on the input to open the calendar when the input element is clicked

- hide the calendar component
- show the calendar component when I click on the input element

Let's go,
```

# singleCalendar.jsx

import { useState } from 'react'

import { DateRange } from 'react-date-range'

import { CalendarIcon } from '../assets/calendaricon'

  

export const SingleCalendar = () => {

  const [open, setOpen] = useState(false)

  const [state, setState] = useState([

    {

      startDate: new Date(),

      endDate: new Date(),

      key: 'selection',

    },

  ])

  

  console.log({ state })

  

  return (

    <div className='container'>

      <div className='element-container'>

        <div className={`dropdown ${open ? 'active' : 'inactive'}`}>

          <DateRange

            className='calendarStyle'

            onChange={(item) => setState([item.selection])}

            ranges={state}

            showSelectionPreview={false}

            editableDateInputs={false}

            showMonthAndYearPickers={false}

            showDateDisplay={false}

            rangeColors={['#4C988E', '#4C988E', '#000000']}

            direction='horizontal'

          />

        </div>

        <div className='single-calendar-input'>

          <input type='text' readOnly onClick={() => setOpen(!open)} />

          <div className='icon'>

            <CalendarIcon />

          </div>

        </div>

      </div>

    </div>

  )

}

```

Your app should now be hidden and will toggle the visible/hidden state when the input element is clicked.


### Show the value of the `DateRange` state in the input element

```

import { useState } from 'react'

import { DateRange } from 'react-date-range'

export const SingleCalendar = () => {

  const [open, setOpen] = useState(false)

  const [state, setState] = useState([

    {

      startDate: new Date(),

      endDate: new Date(),

      key: 'selection',

    },

  ])

  return (

    <div className='container'>

      <div className='element-container'>

        <input

          type='text'

          className='single-calendar-input'

          onClick={() => {

            setOpen(!open)

          }}

++          readOnly

++          value={`${state[0].startDate} - ${state[0].endDate}`}

        />

        <div className={`dropdown ${open ? 'active' : 'inactive'}`}>

          <DateRange

            className='calendarStyle'

            onChange={(item) => setState([item.selection])}

            ranges={state}

            showSelectionPreview={false}

            editableDateInputs={false}

            showMonthAndYearPickers={false}

            showDateDisplay={false}

            rangeColors={['#4C988E', '#4C988E', '#000000']}

            direction='horizontal'

          />

        </div>

      </div>

    </div>

  )

}

```

> You will see the unformatted date value inside the input element

![https://res.cloudinary.com/diggungrj/image/upload/v1683865344/calendar-5_h83fhc.png](https://res.cloudinary.com/diggungrj/image/upload/v1683865344/calendar-5_h83fhc.png)

### Format the date inside the input element
```

import { useState, useEffect } from 'react'

import { DateRange } from 'react-date-range'

import { CalendarIcon } from '../assets/calendaricon'

import { format } from 'date-fns'

  

export const SingleCalendar = () => {

  const [open, setOpen] = useState(false)

  const [state, setState] = useState([

    {

      startDate: new Date(),

      endDate: new Date(),

      key: 'selection',

    },

  ])

  
  const [formatDate, setFormatDate] = useState({

    startDate: new Date(),

  

    endDate: new Date(),

  })

  
  useEffect(() => {

    setFormatDate((prev) => {

      return {

        ...prev,

  

        startDate: format(state[0].startDate, 'dd/MM/yyyy'),

  

        endDate: format(state[0].endDate, 'dd/MM/yyyy'),

      }

    })

  }, [state])

  
  // console.log({ state })

  return (

    <div className='container'>

      <div className='element-container'>

        <div className={`dropdown ${open ? 'active' : 'inactive'}`}>

          <DateRange

            className='calendarStyle'

            onChange={(item) => setState([item.selection])}

            ranges={state}

            showSelectionPreview={false}

            editableDateInputs={false}

            showMonthAndYearPickers={false}

            showDateDisplay={false}

            rangeColors={['#4C988E', '#4C988E', '#000000']}

            direction='horizontal'

          />

        </div>

        <div className='single-calendar-input'>

          <input

            type='text'

            readOnly

            onClick={() => setOpen(!open)}

            value={`${formatDate.startDate}-${formatDate.endDate}`}

          />

          <div className='icon'>

            <CalendarIcon />

          </div>

        </div>

      </div>

    </div>
  )
}

```

> you may be wondering why I did not use the format method directly inside my component, the reason is because of an error caused by using format method inside the input element to directly format the value but it will throw an  [error](https://stackoverflow.com/questions/73602690/uncaught-error-minified-react-error-425-help-me) . 

![https://res.cloudinary.com/diggungrj/image/upload/v1683865344/calendar-6_lcuyis.png](https://res.cloudinary.com/diggungrj/image/upload/v1683865344/calendar-6_lcuyis.png)

### Finally, handle click outside so that when I click outside the component or the body of the page the calendar will close

```

# singleCalendar.jsx

import { useState, useEffect, useRef } from 'react'

import { DateRange } from 'react-date-range'

import { CalendarIcon } from '../assets/calendaricon'

import { format } from 'date-fns'

  

export const SingleCalendar = () => {

  const [open, setOpen] = useState(false)

  const [state, setState] = useState([

    {

      startDate: new Date(),

      endDate: new Date(),

      key: 'selection',

    },

  ])

  
  const [formatDate, setFormatDate] = useState({

    startDate: new Date(),

    endDate: new Date(),

  })

  useEffect(() => {

    setFormatDate((prev) => {

      return {

        ...prev,

  

        startDate: format(state[0].startDate, 'dd/MM/yyyy'),

  

        endDate: format(state[0].endDate, 'dd/MM/yyyy'),

      }

    })

  }, [state])

  

  // console.log({ state })

  

  // handle click outside

  const calendarRef = useRef()

  

  useEffect(() => {

    const handler = (e) => {

      if (!calendarRef?.current.contains(e.target)) {

        setOpen(false)

      }

    }

  

    document.addEventListener('mousedown', handler)

  

    return () => {

      document.removeEventListener('mousedown', handler)

    }

  })

  

  return (

    <div className='container'>

      <div className='element-container' ref={calendarRef}>

        <div className={`dropdown ${open ? 'active' : 'inactive'}`}>

          <DateRange

            className='calendarStyle'

            onChange={(item) => setState([item.selection])}

            ranges={state}

            showSelectionPreview={false}

            editableDateInputs={false}

            showMonthAndYearPickers={false}

            showDateDisplay={false}

            rangeColors={['#4C988E', '#4C988E', '#000000']}

            direction='horizontal'

          />

        </div>

  

        <div className='single-calendar-input'>

          <input

            type='text'

            readOnly

            onClick={() => setOpen(!open)}

            value={`${formatDate.startDate}-${formatDate.endDate}`}

          />

          <div className='icon'>

            <CalendarIcon />

          </div>

        </div>

      </div>

    </div>

  )

}

```

The complete source code can be found [here](https://github.com/davieoba/calendar-app)