Back to Blog
Close-up of programming code on a laptop screen with blue ambient lighting
Framework
July 2, 2026
8 min read

How to Add a Calendar to a React App (Without the Bloat)

By SimpleCalendarJS Team

SimpleCalendarJS~14 KB gzipped · Zero dependencies · Any framework

You need to add a calendar to your React app. You search "React calendar library," and within five minutes you're comparing six packages, each with its own adapter layer, localizer requirement, or plugin system. The calendar itself is a solved problem — the hard part in 2026 is choosing the option that won't bloat your bundle or lock you into a single framework. Here's a clear breakdown of your options and a working implementation you can drop into any React project today.

The React calendar landscape in 2026

The React ecosystem has no shortage of calendar libraries. The challenge is that most of them were built for different eras or different problems than what you actually need.

Date pickers (react-calendar, react-day-picker, react-datepicker) let users select a date. They render a single month grid and return a value. If you just need a date input for a form, these are the right tool — react-day-picker alone powers over 6 million weekly npm downloads as the foundation for Shadcn/UI's calendar component.

Event calendars (react-big-calendar, FullCalendar, DHTMLX) show events on a month/week/day grid. They handle event rendering, time slots, and navigation. This is what most developers mean when they say "add a calendar to my React app."

The problem is that every popular event calendar for React comes with baggage:

LibraryGzipped SizeExtra RequirementsFramework
react-big-calendar~50 KBLocalizer library (16–64 KB)React only
FullCalendar~43 KB minimumPlugin packages + React adapterMulti-framework
DHTMLX Scheduler~100 KB+Commercial license for most featuresMulti-framework
SimpleCalendarJS~14 KBNoneAny framework

react-big-calendar requires a mandatory localizer — Moment.js, date-fns, Day.js, or Globalize — just to render. That's a hard dependency on a date library you might not use anywhere else in your app. FullCalendar requires @fullcalendar/react, @fullcalendar/core, and at least one view plugin before anything appears on screen. These are real costs measured in kilobytes and configuration time.

Option 1: The React-specific path

If you want a React-native component that participates in React's rendering lifecycle with controlled props and JSX, react-big-calendar is the most popular choice at roughly 1 million weekly npm downloads. A minimal setup looks like this:

import { Calendar, dayjsLocalizer } from 'react-big-calendar'; import dayjs from 'dayjs'; import 'react-big-calendar/lib/css/react-big-calendar.css'; const localizer = dayjsLocalizer(dayjs); function MyCalendar({ events }) { return ( <div style={{ height: 600 }}> <Calendar localizer={localizer} events={events} startAccessor="start" endAccessor="end" /> </div> ); }

This works, but note the trade-offs:

  • You must set an explicit container height — the calendar won't render without it
  • The Day.js localizer has a known webpack issue (GitHub #2398) where Day.js code is included in the output regardless of which localizer you use
  • React 19 support is still tracked in an open issue (GitHub #2701), with reports of navigation buttons breaking after framework upgrades
  • Styling customisation means overriding deeply nested CSS selectors — the library's own docs warn that "changing styles can cause rendering issues"

Total bundle cost: ~50 KB (react-big-calendar) + ~5–10 KB (Day.js) = ~60 KB gzipped minimum.

Option 2: The vanilla JS path (recommended)

A vanilla JavaScript calendar library works in React the same way any imperative DOM library does: useRef for the container, useEffect for lifecycle management. This is the exact pattern React's official documentation recommends for integrating third-party DOM libraries.

Here's how to add a calendar to a React app using SimpleCalendarJS~14 KB gzipped, zero dependencies, zero configuration:

npm install simple-calendar-js
import { useEffect, useRef } from 'react'; import SimpleCalendarJs from 'simple-calendar-js'; import 'simple-calendar-js/dist/simple-calendar-js.min.css'; function Calendar({ onEventClick }) { const containerRef = useRef(null); const calendarRef = useRef(null); useEffect(() => { if (!containerRef.current) return; calendarRef.current = new SimpleCalendarJs(containerRef.current, { defaultView: 'month', locale: 'en-US', enabledViews: ['month', 'week', 'day'], fetchEvents: async (start, end) => { const res = await fetch( `/api/events?from=${start.toISOString()}&to=${end.toISOString()}` ); return res.json(); }, onEventClick: (event) => onEventClick?.(event), onSlotClick: (date) => console.log('Slot clicked:', date), }); return () => calendarRef.current?.destroy(); }, []); return <div ref={containerRef} />; } export default Calendar;

That's a complete, production-ready React calendar component in 20 lines. No localizer. No adapter package. No explicit height hack. No plugin registration.

What this gives you

  • Month, week, and day views — toggle with the built-in toolbar or call calendarRef.current.setView('week') from your own buttons
  • Async event fetching — the fetchEvents callback fires with the visible date range on every navigation, so you only load what's on screen
  • Click handlersonEventClick for existing events, onSlotClick for empty time slots (wire it to a "create event" modal)
  • 34+ locales built in — pass locale: 'pt-BR' or locale: 'ja-JP' and the calendar renders in that language
  • Automatic cleanup — the destroy() call in the useEffect return function prevents memory leaks on unmount

Theming the calendar in React

The entire visual layer uses CSS custom properties. This works identically whether you're using CSS modules, Tailwind's @layer, styled-components, or a global stylesheet:

.uc-calendar { --cal-primary: #6366f1; --cal-primary-dark: #4f46e5; --cal-today-bg: #e0e7ff; --cal-font-size: 14px; }

Four lines of CSS and your calendar matches your brand. No SASS pipeline, no eventPropGetter function, no specificity overrides.

For dark mode, wrap the variables in a media query:

@media (prefers-color-scheme: dark) { .uc-calendar { --cal-bg: #1e1e2e; --cal-text: #cdd6f4; --cal-border: #313244; --cal-today-bg: #313244; } }

Programmatic control from React

Because SimpleCalendarJS exposes imperative methods on the calendar instance, you can build custom navigation UI that lives outside the calendar:

function CalendarPage() { const calendarRef = useRef(null); // ... calendar setup in useEffect ... return ( <div> <div className="toolbar"> <button onClick={() => calendarRef.current?.prev()}>Previous</button> <button onClick={() => calendarRef.current?.today()}>Today</button> <button onClick={() => calendarRef.current?.next()}>Next</button> <button onClick={() => calendarRef.current?.setView('month')}>Month</button> <button onClick={() => calendarRef.current?.setView('week')}>Week</button> <button onClick={() => calendarRef.current?.setView('day')}>Day</button> </div> <div ref={containerRef} /> </div> ); }

This pattern gives you full control over the toolbar's design and placement — something that's surprisingly difficult with React-specific calendar libraries that manage their own header UI.

Bundle size comparison: what you're actually shipping

The numbers matter because every kilobyte of JavaScript directly impacts your Core Web Vitals — specifically Largest Contentful Paint (LCP) and Total Blocking Time (TBT), both Google ranking signals.

SetupGzipped Sizenpm Packages
react-big-calendar + Day.js localizer~60 KB3
FullCalendar + React adapter + daygrid~50 KB4
react-calendar (date picker only)~15 KB2
SimpleCalendarJS (event calendar)~14 KB1

SimpleCalendarJS delivers month, week, and day event views at roughly the same weight as a date-picker-only library — and 4x lighter than react-big-calendar's minimum setup.

When to use a React-specific calendar instead

There are legitimate reasons to choose a React-native calendar component:

  • Controlled component pattern: If your calendar's view, date, and events must be driven entirely by React state and props (e.g. for time-travel debugging or server-driven UI), a React component handles this natively.
  • Agenda/list view: react-big-calendar includes a built-in agenda view for displaying events in a linear, scrollable list. SimpleCalendarJS focuses on grid-based month, week, and day views.
  • Drag-and-drop rescheduling: react-big-calendar has mature (if manually configured) drag-and-drop support for moving and resizing events on the grid.
  • Deep React ecosystem coupling: If you're building a design system where every component must be a React component that accepts className and ref props, a vanilla JS library doesn't fit that contract.

For the majority of React apps that need to display events on a calendar and let users interact with them, a vanilla JS approach is simpler, lighter, and more portable.

Summary

  • React has no built-in calendar — you need a library, and the choice impacts your bundle size by 14–100+ KB gzipped
  • react-big-calendar (~50 KB + localizer) and FullCalendar (~43 KB + plugins) are powerful but carry significant weight and configuration overhead
  • The useEffect + useRef pattern is React's recommended approach for integrating any vanilla JavaScript DOM library — it's clean, idiomatic, and well-documented
  • SimpleCalendarJS ships a full event calendar (month, week, day views, async event fetching, click handlers, 34+ locales) in ~14 KB gzipped with zero dependencies
  • Theme with CSS custom properties instead of fighting generated stylesheets — four variables and your calendar matches your brand

Sources & Further Reading

Research & References

Image Credits

All images free to use under the Pexels License.

Frequently Asked Questions

What is the best calendar library for React?

It depends on what you need. For date pickers, react-day-picker (~12 KB) or react-calendar (~15 KB) are solid choices. For event-driven scheduling views (month, week, day), react-big-calendar (~50 KB + localizer) and FullCalendar (~43 KB+ with plugins) are the most popular — but both carry significant bundle weight. SimpleCalendarJS (~14 KB, zero dependencies) offers month, week, and day views with event support and works in React via a simple useEffect/useRef pattern.

How do I add a calendar to a React app?

Install a calendar library via npm, import it into your component, and render it. With React-specific libraries you use JSX components directly. With vanilla JS libraries like SimpleCalendarJS, you use a useRef to target a container element and a useEffect to initialise and clean up the calendar instance.

Can I use a vanilla JavaScript calendar library in React?

Yes. The standard pattern is to use useRef for the DOM container and useEffect for initialization and cleanup. This is the same approach React's own documentation recommends for integrating any imperative DOM library. It works with any vanilla JS calendar — including SimpleCalendarJS, Pikaday, or custom solutions.

Do I need a localizer for react-big-calendar?

Yes. react-big-calendar has no built-in date handling. You must install and configure a separate localizer library — Moment.js, date-fns, Day.js, or Globalize — before the calendar renders. This adds 16–64 KB gzipped to your bundle depending on the library you choose, and it's a mandatory setup step.

Is FullCalendar free for React?

FullCalendar's core and basic view plugins are MIT-licensed and free. However, you need the @fullcalendar/react adapter package, and advanced features like resource scheduling and timeline views require a paid premium license starting at $480 per developer for commercial use.

How much does a React calendar library add to my bundle size?

Bundle impact varies widely. react-calendar adds ~15 KB gzipped. react-big-calendar adds ~50 KB plus a required localizer (16–64 KB more). FullCalendar starts at ~43 KB for a minimal setup and grows with each plugin. SimpleCalendarJS adds ~14 KB gzipped with zero additional dependencies.

📅

Add a calendar to your app today

Free for personal projects. $49/year or $199 lifetime per commercial project.