Create a React Calendar Component with Events

As a React developer, I’ve worked on a variety of projects that require calendar components, from booking systems to event schedulers. One thing I’ve learned is that building a calendar with event handling can be easy if you choose the right approach and tools.

In this article, I’ll walk you through creating a React calendar component that displays events, allows users to interact with dates, and is easy to customize for your needs. Whether you’re building an appointment scheduler for a US-based healthcare app or a local event planner, this tutorial will help you get started quickly.

Build a Custom React Calendar Component

Out of the box, React doesn’t provide a calendar component. While there are many third-party libraries like react-big-calendar or fullcalendar-react, sometimes you want a lightweight, customizable calendar tailored exactly to your use case.

From my experience, building a calendar from scratch or using minimal dependencies helps:

  • Keep your bundle size small
  • Control styling and UX
  • Easily integrate with your backend or state management

Methods to Build a React Calendar with Events

There are two main approaches I recommend:

  1. Build a Calendar from Scratch Using Date Libraries
  2. Use a Lightweight Calendar Library and Extend It

I’ll explain both methods with code examples, so you can pick what suits your project best.

Method 1: Build a Calendar from Scratch Using date-fns

date-fns is a popular, lightweight date utility library. It simplifies date manipulation and formatting, which is crucial for building calendars.

Step 1: Set up React Project

If you don’t have a React app ready, create one using:

npx create-react-app react-calendar-events
cd react-calendar-events
npm install date-fns

Step 2: Create the Calendar Component

Here’s a full React component that renders a monthly calendar with clickable dates and displays events for selected dates.

import React, { useState } from 'react';
import { startOfMonth, endOfMonth, startOfWeek, endOfWeek, addDays, format, isSameMonth, isSameDay } from 'date-fns';

const events = {
  '2025-11-28': [{ id: 1, title: 'Veterans Day Parade', time: '10:00 AM' }],
  '2025-11-30': [{ id: 2, title: 'Thanksgiving Dinner', time: '6:00 PM' }],
  '2025-12-05': [{ id: 3, title: 'Community Meeting', time: '4:00 PM' }],
};

function Calendar() {
  const [currentMonth, setCurrentMonth] = useState(new Date());
  const [selectedDate, setSelectedDate] = useState(new Date());

  const renderHeader = () => {
    const dateFormat = "MMMM yyyy";

    return (
      <div className="header row flex-middle">
        <div className="col col-start">
          <div className="icon" onClick={prevMonth}>‹</div>
        </div>
        <div className="col col-center">
          <span>{format(currentMonth, dateFormat)}</span>
        </div>
        <div className="col col-end" onClick={nextMonth}>
          <div className="icon">›</div>
        </div>
      </div>
    );
  };

  const renderDays = () => {
    const days = [];
    const dateFormat = "EEEE";
    const startDate = startOfWeek(currentMonth);

    for (let i = 0; i < 7; i++) {
      days.push(
        <div className="col col-center" key={i}>
          {format(addDays(startDate, i), dateFormat)}
        </div>
      );
    }

    return <div className="days row">{days}</div>;
  };

  const renderCells = () => {
    const monthStart = startOfMonth(currentMonth);
    const monthEnd = endOfMonth(monthStart);
    const startDate = startOfWeek(monthStart);
    const endDate = endOfWeek(monthEnd);

    const rows = [];
    let days = [];
    let day = startDate;
    let formattedDate = '';

    while (day <= endDate) {
      for (let i = 0; i < 7; i++) {
        formattedDate = format(day, 'd');
        const cloneDay = day;

        const isoDate = format(day, 'yyyy-MM-dd');
        const dayEvents = events[isoDate] || [];

        days.push(
          <div
            className={`col cell ${!isSameMonth(day, monthStart)
              ? 'disabled'
              : isSameDay(day, selectedDate) ? 'selected' : ''}`}
            key={day}
            onClick={() => onDateClick(cloneDay)}
          >
            <span className="number">{formattedDate}</span>
            {dayEvents.length > 0 && <span className="event-indicator"></span>}
          </div>
        );
        day = addDays(day, 1);
      }
      rows.push(
        <div className="row" key={day}>
          {days}
        </div>
      );
      days = [];
    }
    return <div className="body">{rows}</div>;
  };

  const onDateClick = day => {
    setSelectedDate(day);
  };

  const nextMonth = () => {
    setCurrentMonth(addDays(currentMonth, 30));
  };

  const prevMonth = () => {
    setCurrentMonth(addDays(currentMonth, -30));
  };

  const renderEvents = () => {
    const isoDate = format(selectedDate, 'yyyy-MM-dd');
    const dayEvents = events[isoDate] || [];

    if (dayEvents.length === 0) {
      return <div>No events for this day.</div>;
    }

    return (
      <ul>
        {dayEvents.map(event => (
          <li key={event.id}>
            <strong>{event.title}</strong> at {event.time}
          </li>
        ))}
      </ul>
    );
  };

  return (
    <div className="calendar">
      {renderHeader()}
      {renderDays()}
      {renderCells()}
      <div className="event-list">
        <h3>Events on {format(selectedDate, 'MMMM d, yyyy')}</h3>
        {renderEvents()}
      </div>
    </div>
  );
}

export default Calendar;

Step 3: Add Basic Styles

Add this CSS to App.css or your preferred stylesheet to make the calendar readable:

.calendar {
  width: 350px;
  margin: 20px auto;
  font-family: Arial, sans-serif;
}

.header {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  background: #0078d7;
  color: white;
  border-radius: 5px 5px 0 0;
}

.icon {
  cursor: pointer;
  user-select: none;
  font-size: 20px;
}

.days {
  display: flex;
  background: #f0f0f0;
  padding: 5px 0;
}

.col {
  flex: 1;
  text-align: center;
  padding: 8px 0;
}

.body .row {
  display: flex;
}

.cell {
  flex: 1;
  height: 60px;
  border: 1px solid #ddd;
  padding: 5px;
  cursor: pointer;
  position: relative;
}

.cell.disabled {
  color: #ccc;
  cursor: default;
}

.cell.selected {
  background: #0078d7;
  color: white;
}

.number {
  display: block;
  font-weight: bold;
}

.event-indicator {
  width: 6px;
  height: 6px;
  background: red;
  border-radius: 50%;
  position: absolute;
  bottom: 5px;
  right: 5px;
}

.event-list {
  margin-top: 20px;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

Step 4: Use the Calendar Component

In your App.js, import and use the calendar:

import React from 'react';
import Calendar from './Calendar';

function App() {
  return (
    <div>
      <h1>Community Events Calendar</h1>
      <Calendar />
    </div>
  );
}

export default App;

You can refer to the screenshot below to see the output.

React Calendar Component with Events

Method 2: Use react-calendar Library with Custom Event Handling

If you want a quick solution, the react-calendar library is a great choice. It provides a calendar UI, and you can extend it to show events.

Step 1: Install react-calendar

npm install react-calendar

Step 2: Create a Calendar with Events

import React, { useState } from 'react';
import Calendar from 'react-calendar';
import 'react-calendar/dist/Calendar.css';

const events = {
  '2025-11-28': [{ id: 1, title: 'Veterans Day Parade', time: '10:00 AM' }],
  '2025-11-30': [{ id: 2, title: 'Thanksgiving Dinner', time: '6:00 PM' }],
  '2025-12-05': [{ id: 3, title: 'Community Meeting', time: '4:00 PM' }],
};

function EventCalendar() {
  const [date, setDate] = useState(new Date());

  const tileContent = ({ date, view }) => {
    const isoDate = date.toISOString().split('T')[0];
    if (view === 'month' && events[isoDate]) {
      return <div className="event-dot"></div>;
    }
    return null;
  };

  const onChange = selectedDate => {
    setDate(selectedDate);
  };

  const isoDate = date.toISOString().split('T')[0];
  const dayEvents = events[isoDate] || [];

  return (
    <div>
      <Calendar onChange={onChange} value={date} tileContent={tileContent} />
      <h3>Events on {date.toDateString()}</h3>
      {dayEvents.length === 0 ? (
        <p>No events for this day.</p>
      ) : (
        <ul>
          {dayEvents.map(event => (
            <li key={event.id}>
              <strong>{event.title}</strong> at {event.time}
            </li>
          ))}
        </ul>
      )}
      <style>{`
        .event-dot {
          height: 6px;
          width: 6px;
          background: red;
          border-radius: 50%;
          margin-top: 2px;
          margin-left: auto;
          margin-right: auto;
        }
      `}</style>
    </div>
  );
}

export default EventCalendar;

You can refer to the screenshot below to see the output.

Create React Calendar Component with Events

This method is faster to implement and works well if you don’t want to build everything from scratch.

Building a React calendar component with event handling can be as simple or complex as your project requires. From my experience, the custom approach with date-fns offers full control and is perfect when you need a tailored UI. Meanwhile, libraries like react-calendar provide quick solutions with decent flexibility.

Choose the method that fits your timeline and project needs. Either way, you’ll have a functional calendar that can display and handle events for your US-based applications, like community events, holiday schedules, or appointment bookings.

You may also read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.