How to Build an Interactive Calendar in React with
react-big-calendar
Create, Edit, and Manage Events in Style
Meta Description
Learn how to integrate `react-big-calendar`
into your React app with event creation, editing, and popup modals. Step-by-step
guide with code examples for building a full-featured calendar UI.
Overview
If you're building a React app and want to
add a feature-rich calendar that allows users to view, create, and edit events,
`react-big-calendar` is one of the best tools for the job.
In this tutorial, you’ll learn how to:
- Set up `react-big-calendar` in a React
project
- Add 5 sample events
- Open a popup form when a date slot is
clicked to add new events
- Edit events by clicking on them
- Maintain clean component structure with a
dedicated popup component
Step 1: Install Dependencies
Install the required packages:
npm install react-big-calendar moment
Also install styles:
npm install react-big-calendar@latest
moment@latest
Step 2: Set Up the Calendar Component
Create `CalendarComponent.jsx` and
initialize `react-big-calendar` with moment localizer.
Code:
import { useState } from"react";
import {
Calendar as BigCalendar,
momentLocalizer,
Views
} from"react-big-calendar";
import moment from"moment";
import"react-big-calendar/lib/css/react-big-calendar.css";
import EventPopup from"./EventPopup"; // <- Importing the popup component
const localizer = momentLocalizer(moment);
const initialEvents = [
{
id: 1,
title: "Meeting with John",
start: new Date(moment().add(1, 'days').set({ hour: 10, minute: 0 })),
end: new Date(moment().add(1, 'days').set({ hour: 11, minute: 0 }))
},
{
id: 2,
title: "Lunch with Sarah",
start: new Date(moment().subtract(20, 'days').set({ hour: 12, minute: 0 })),
end: new Date(moment().subtract(20, 'days').set({ hour: 13, minute: 0 }))
},
{
id: 3,
title: "Project Deadline",
start: new Date(moment().subtract(3, 'days').startOf("day")),
end: new Date(moment().subtract(3, 'days').endOf("day"))
},
{
id: 4,
title: "Workshop",
start: new Date(moment().subtract(10, 'days').set({ hour: 9, minute: 0 })),
end: new Date(moment().subtract(10, 'days').set({ hour: 17, minute: 0 }))
},
{
id: 5,
title: "Team Standup",
start: new Date(moment().subtract(15, 'days').set({ hour: 9, minute: 30 })),
end: new Date(moment().subtract(15, 'days').set({ hour: 10, minute: 0 }))
}
];
export default function CalendarComponent() {
const [events, setEvents] = useState(initialEvents);
const [selectedDate, setSelectedDate] = useState(null);
const [isOpenEvent, setIsOpenEvent] = useState(false);
const [selectedEvent, setSelectedEvent] = useState(null);
const handleSelectEvent = (event) => {
setSelectedEvent(event);
setSelectedDate(null);
setIsOpenEvent(true);
};
const handleSelectSlot = (slotInfo) => {
setSelectedDate(slotInfo.start);
setSelectedEvent(null);
setIsOpenEvent(true);
};
const handleSaveEvent = (eventData) => {
if (eventData.id) {
// Editing existing
setEvents((prev) =>
prev.map((ev) => (ev.id === eventData.id ? eventData : ev))
);
} else {
// Adding new
const newEvent = {
...eventData,
id: events.length + 1
};
setEvents((prev) => [...prev, newEvent]);
}
setIsOpenEvent(false);
setSelectedDate(null);
setSelectedEvent(null);
};
return (
<>
<div style={{ marginLeft: "100px", marginRight: "100px", marginTop: "100px" }}>
<BigCalendar
selectable
localizer={localizer}
events={events}
startAccessor="start"
endAccessor="end"
onSelectSlot={handleSelectSlot}
onSelectEvent={handleSelectEvent}
style={{ height: '77vh' }}
/>
</div>
{isOpenEvent && (
<EventPopup
isOpen={isOpenEvent}
onClose={() => setIsOpenEvent(false)}
onSave={handleSaveEvent}
date={selectedDate}
event={selectedEvent}
/>
)}
</>
);
}
Step 3: Create the Event Popup Component
Now, let’s build the reusable `EventPopup`
component to handle both adding and editing events.
Code:
import React, { useEffect, useState } from"react";
exportdefaultfunction EventPopup({ isOpen, onClose, onSave, date, event }) {
const [title, setTitle] = useState("");
const [start, setStart] = useState("");
const [end, setEnd] = useState("");
useEffect(() => {
if (event) {
setTitle(event.title || "");
setStart(event.start.toISOString().slice(0, 16));
setEnd(event.end.toISOString().slice(0, 16));
} else if (date) {
const defaultStart = new Date(date);
const defaultEnd = new Date(defaultStart.getTime() + 60 * 60 * 1000); // 1 hour later
setStart(defaultStart.toISOString().slice(0, 16));
setEnd(defaultEnd.toISOString().slice(0, 16));
setTitle("");
}
}, [date, event]);
const handleSubmit = (e) => {
e.preventDefault();
onSave({
id: event?.id,
title,
start: new Date(start),
end: new Date(end),
});
};
if (!isOpen) return null;
return (
<div style={{
position: "fixed",
top: 0, left: 0,
width: "100vw", height: "100vh",
backgroundColor: "rgba(0,0,0,0.4)",
display: "flex", alignItems: "center", justifyContent: "center",
zIndex: "10"
}}>
<div style={{ backgroundColor: "white", padding: "20px", borderRadius: "8px", width: "400px" }}>
<h2>{event ? "Edit Event" : "Add Event"}</h2>
<form onSubmit={handleSubmit}>
<div>
<label>Title:</label>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
required
style={{ width: "90%", padding: "8px", marginBottom: "10px" }}
/>
</div>
<div>
<label>Start:</label>
<input
type="datetime-local"
value={start}
onChange={(e) => setStart(e.target.value)}
required
style={{ width: "90%", padding: "8px", marginBottom: "10px" }}
/>
</div>
<div>
<label>End:</label>
<input
type="datetime-local"
value={end}
onChange={(e) => setEnd(e.target.value)}
required
style={{ width: "90%", padding: "8px", marginBottom: "10px" }}
/>
</div>
<button type="submit"style={{ marginRight: "10px", marginTop: "15px" }}>Save</button>
<button type="button"onClick={onClose}>Cancel</button>
</form>
</div>
</div>
);
}
Result
You now have a fully functional calendar in
React with:
- 5 sample events
- Popup for adding new events by clicking a
date
- Edit functionality by clicking existing
events
- Clean component separation