Reputation: 4454
I'm trying to use React Big Calendar with typescript. After reading the docs, I am able to get the calendar itself to display (setting height very important!), however I cannot get any events to show up. I am seeing that the array of events I have is populating correctly, and this is code I took from the examples and made it TS friendly and also for useState. From reading other answers, I also made sure to check the accessors but it didn't have an impact whether it was defined or not.
For anything Typescript related that I did, the source for it is here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-big-calendar/react-big-calendar-tests.tsx
Here is how I display my component:
import React from 'react';
import moment from 'moment'
import { momentLocalizer } from 'react-big-calendar';
import 'react-big-calendar/lib/css/react-big-calendar.css';
import SelectableCalendar from './SelectableCalendar';
const localizer = momentLocalizer(moment);
export default function Availability() {
return (
<div style={{ height: "100vh" }}>
<SelectableCalendar localizer={localizer} />
</div>
);
}
Here is my component itself:
import React, { useState } from 'react'
import { Calendar, View, DateLocalizer } from 'react-big-calendar'
import moment from 'moment';
const allViews: View[] = ['agenda', 'day', 'week', 'month'];
interface Props {
localizer: DateLocalizer;
}
class CalendarEvent {
title: string;
allDay: boolean;
start: Date;
end: Date;
desc: string;
resourceId?: string;
tooltip?: string;
constructor(_title: string, _start: Date, _endDate: Date, _allDay?: boolean, _desc?: string, _resourceId?: string) {
this.title = _title;
this.allDay = _allDay || false;
this.start = _start;
this.end = _endDate;
this.desc = _desc || '';
this.resourceId = _resourceId;
}
}
export default function SelectableCalendar ({ localizer }: Props) {
const [events, setEvents] = useState([] as CalendarEvent[]);
const handleSelect = ({ start, end }) => {
const title = window.prompt('New Event name')
if (title) {
let newEvent = {} as CalendarEvent;
newEvent.start = moment(start).toDate();
newEvent.end = moment(end).toDate();
newEvent.title = title;
events.push(newEvent)
setEvents(events)
}
}
return (
<>
<div>
<strong>
Click an event to see more info, or drag the mouse over the calendar
to select a date/time range.
</strong>
</div>
<Calendar
selectable
localizer={localizer}
events={events}
defaultView='month'
views={allViews}
defaultDate={new Date(2020, 4, 21)}
onSelectEvent={event => alert(event.title)}
onSelectSlot={handleSelect}
startAccessor='start'
endAccessor='end'
titleAccessor='title'
/>
</>
)
}
What am I missing?
Upvotes: 1
Views: 5192
Reputation: 1362
The issue is that you are mutating your state and then setting it. React doesn't recognize a change (since you already made it to the state directly) and therefore doesn't re-render the component.
This can be fixed by setting the new state directly with the changes, i.e.:
if (title) {
let newEvent = {} as CalendarEvent;
newEvent.start = moment(start).toDate();
newEvent.end = moment(end).toDate();
newEvent.title = title;
// Erroneous code:
// events.push(newEvent)
// setEvents(events)
setEvents([
...events,
newEvent
])
}
Here is a playground with your code and the above fix that shows this is working: https://codesandbox.io/s/currying-bush-2c3hc?file=/src/App.tsx
Upvotes: 4