如何在 nextjs 中正确实现 toast-ui/calendar
How to properly implement toast-ui/calendar in nextjs
我正在尝试实现@toast-ui/react-calendar,最初我得到的是 window is not defined
但在实现修复后我得到了这里 https://github.com/nhn/toast-ui.react-calendar/issues/39,我得到了这个 未处理的运行时错误错误:元素类型无效:应为字符串(对于内置组件)或 class/function(对于复合组件)但得到:对象。您可能忘记从定义它的文件中导出您的组件,或者您可能混淆了默认导入和命名导入。检查 __WEBPACK_DEFAULT_EXPORT__
.
的渲染方法
这是我当前的代码
CalendarPage.js
import React from 'react';
import Calendar from '@toast-ui/react-calendar';
import 'tui-calendar/dist/tui-calendar.css';
import 'tui-date-picker/dist/tui-date-picker.css';
import 'tui-time-picker/dist/tui-time-picker.css';
export default (props) => <Calendar {...props} ref={props.forwardedRef} />;
日程>index.jsx
import { forwardRef, useCallback, useRef, useState } from 'react';
import dynamic from 'next/dynamic';
const TuiCalendar = dynamic(() => import('@components/calendars/CalendarPage'), { ssr: false });
const CalendarWithForwardedRef = forwardRef((props, ref) => (
<TuiCalendar {...props} forwardedRef={ref} />
));
const start = new Date();
const end = new Date(new Date().setMinutes(start.getMinutes() + 30));
const schedules = [
{
calendarId: '1',
category: 'time',
isVisible: true,
title: 'Study',
id: '1',
body: 'Test',
start,
end,
},
{
calendarId: '2',
category: 'time',
isVisible: true,
title: 'Meeting',
id: '2',
body: 'Description',
start: new Date(new Date().setHours(start.getHours() + 1)),
end: new Date(new Date().setHours(start.getHours() + 2)),
},
];
const calendars = [
{
id: '1',
name: 'My Calendar',
color: '#ffffff',
bgColor: '#9e5fff',
dragBgColor: '#9e5fff',
borderColor: '#9e5fff',
},
{
id: '2',
name: 'Company',
color: '#ffffff',
bgColor: '#00a9ff',
dragBgColor: '#00a9ff',
borderColor: '#00a9ff',
},
];
const SchedulePage = () => {
const cal = useRef(null);
const onClickSchedule = useCallback((e) => {
const { calendarId, id } = e.schedule;
const el = cal.current.calendarInst.getElement(id, calendarId);
console.log(e, el.getBoundingClientRect());
}, []);
const onBeforeCreateSchedule = useCallback((scheduleData) => {
console.log(scheduleData);
const schedule = {
id: String(Math.random()),
title: scheduleData.title,
isAllDay: scheduleData.isAllDay,
start: scheduleData.start,
end: scheduleData.end,
category: scheduleData.isAllDay ? 'allday' : 'time',
dueDateClass: '',
location: scheduleData.location,
raw: {
class: scheduleData.raw['class'],
},
state: scheduleData.state,
};
cal.current.calendarInst.createSchedules([schedule]);
}, []);
const onBeforeDeleteSchedule = useCallback((res) => {
console.log(res);
const { id, calendarId } = res.schedule;
cal.current.calendarInst.deleteSchedule(id, calendarId);
}, []);
const onBeforeUpdateSchedule = useCallback((e) => {
console.log(e);
const { schedule, changes } = e;
cal.current.calendarInst.updateSchedule(schedule.id, schedule.calendarId, changes);
}, []);
function _getFormattedTime(time) {
const date = new Date(time);
const h = date.getHours();
const m = date.getMinutes();
return `${h}:${m}`;
}
function _getTimeTemplate(schedule, isAllDay) {
var html = [];
if (!isAllDay) {
html.push('<strong>' + _getFormattedTime(schedule.start) + '</strong> ');
}
if (schedule.isPrivate) {
html.push('<span class="calendar-font-icon ic-lock-b"></span>');
html.push(' Private');
} else {
if (schedule.isReadOnly) {
html.push('<span class="calendar-font-icon ic-readonly-b"></span>');
} else if (schedule.recurrenceRule) {
html.push('<span class="calendar-font-icon ic-repeat-b"></span>');
} else if (schedule.attendees.length) {
html.push('<span class="calendar-font-icon ic-user-b"></span>');
} else if (schedule.location) {
html.push('<span class="calendar-font-icon ic-location-b"></span>');
}
html.push(' ' + schedule.title);
}
return html.join('');
}
const templates = {
time: function (schedule) {
console.log(schedule);
return _getTimeTemplate(schedule, false);
},
};
return (
<div className='App'>
<h1>Welcome to TOAST Ui Calendar</h1>
<CalendarWithForwardedRef
ref={cal}
height='1000px'
useCreationPopup={true}
useDetailPopup={true}
calendars={calendars}
schedules={schedules}
onClickSchedule={onClickSchedule}
onBeforeCreateSchedule={onBeforeCreateSchedule}
onBeforeDeleteSchedule={onBeforeDeleteSchedule}
onBeforeUpdateSchedule={onBeforeUpdateSchedule}></CalendarWithForwardedRef>
</div>
);
};
export default SchedulePage;
我不知道我做错了什么,但我一直收到这个错误
Unhandled Runtime Error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `__WEBPACK_DEFAULT_EXPORT__`.
Call Stack
createFiberFromTypeAndProps
node_modules\react-dom\cjs\react-dom.development.js (25058:0)
createFiberFromElement
node_modules\react-dom\cjs\react-dom.development.js (25086:0)
reconcileSingleElement
node_modules\react-dom\cjs\react-dom.development.js (14052:0)
reconcileChildFibers
node_modules\react-dom\cjs\react-dom.development.js (14112:0)
原来我的代码问题是由冲突的 npm 包引起的,我之前安装了 react-big-calendar 删除修复了问题
我正在尝试实现@toast-ui/react-calendar,最初我得到的是 window is not defined
但在实现修复后我得到了这里 https://github.com/nhn/toast-ui.react-calendar/issues/39,我得到了这个 未处理的运行时错误错误:元素类型无效:应为字符串(对于内置组件)或 class/function(对于复合组件)但得到:对象。您可能忘记从定义它的文件中导出您的组件,或者您可能混淆了默认导入和命名导入。检查 __WEBPACK_DEFAULT_EXPORT__
.
这是我当前的代码
CalendarPage.js
import React from 'react';
import Calendar from '@toast-ui/react-calendar';
import 'tui-calendar/dist/tui-calendar.css';
import 'tui-date-picker/dist/tui-date-picker.css';
import 'tui-time-picker/dist/tui-time-picker.css';
export default (props) => <Calendar {...props} ref={props.forwardedRef} />;
日程>index.jsx
import { forwardRef, useCallback, useRef, useState } from 'react';
import dynamic from 'next/dynamic';
const TuiCalendar = dynamic(() => import('@components/calendars/CalendarPage'), { ssr: false });
const CalendarWithForwardedRef = forwardRef((props, ref) => (
<TuiCalendar {...props} forwardedRef={ref} />
));
const start = new Date();
const end = new Date(new Date().setMinutes(start.getMinutes() + 30));
const schedules = [
{
calendarId: '1',
category: 'time',
isVisible: true,
title: 'Study',
id: '1',
body: 'Test',
start,
end,
},
{
calendarId: '2',
category: 'time',
isVisible: true,
title: 'Meeting',
id: '2',
body: 'Description',
start: new Date(new Date().setHours(start.getHours() + 1)),
end: new Date(new Date().setHours(start.getHours() + 2)),
},
];
const calendars = [
{
id: '1',
name: 'My Calendar',
color: '#ffffff',
bgColor: '#9e5fff',
dragBgColor: '#9e5fff',
borderColor: '#9e5fff',
},
{
id: '2',
name: 'Company',
color: '#ffffff',
bgColor: '#00a9ff',
dragBgColor: '#00a9ff',
borderColor: '#00a9ff',
},
];
const SchedulePage = () => {
const cal = useRef(null);
const onClickSchedule = useCallback((e) => {
const { calendarId, id } = e.schedule;
const el = cal.current.calendarInst.getElement(id, calendarId);
console.log(e, el.getBoundingClientRect());
}, []);
const onBeforeCreateSchedule = useCallback((scheduleData) => {
console.log(scheduleData);
const schedule = {
id: String(Math.random()),
title: scheduleData.title,
isAllDay: scheduleData.isAllDay,
start: scheduleData.start,
end: scheduleData.end,
category: scheduleData.isAllDay ? 'allday' : 'time',
dueDateClass: '',
location: scheduleData.location,
raw: {
class: scheduleData.raw['class'],
},
state: scheduleData.state,
};
cal.current.calendarInst.createSchedules([schedule]);
}, []);
const onBeforeDeleteSchedule = useCallback((res) => {
console.log(res);
const { id, calendarId } = res.schedule;
cal.current.calendarInst.deleteSchedule(id, calendarId);
}, []);
const onBeforeUpdateSchedule = useCallback((e) => {
console.log(e);
const { schedule, changes } = e;
cal.current.calendarInst.updateSchedule(schedule.id, schedule.calendarId, changes);
}, []);
function _getFormattedTime(time) {
const date = new Date(time);
const h = date.getHours();
const m = date.getMinutes();
return `${h}:${m}`;
}
function _getTimeTemplate(schedule, isAllDay) {
var html = [];
if (!isAllDay) {
html.push('<strong>' + _getFormattedTime(schedule.start) + '</strong> ');
}
if (schedule.isPrivate) {
html.push('<span class="calendar-font-icon ic-lock-b"></span>');
html.push(' Private');
} else {
if (schedule.isReadOnly) {
html.push('<span class="calendar-font-icon ic-readonly-b"></span>');
} else if (schedule.recurrenceRule) {
html.push('<span class="calendar-font-icon ic-repeat-b"></span>');
} else if (schedule.attendees.length) {
html.push('<span class="calendar-font-icon ic-user-b"></span>');
} else if (schedule.location) {
html.push('<span class="calendar-font-icon ic-location-b"></span>');
}
html.push(' ' + schedule.title);
}
return html.join('');
}
const templates = {
time: function (schedule) {
console.log(schedule);
return _getTimeTemplate(schedule, false);
},
};
return (
<div className='App'>
<h1>Welcome to TOAST Ui Calendar</h1>
<CalendarWithForwardedRef
ref={cal}
height='1000px'
useCreationPopup={true}
useDetailPopup={true}
calendars={calendars}
schedules={schedules}
onClickSchedule={onClickSchedule}
onBeforeCreateSchedule={onBeforeCreateSchedule}
onBeforeDeleteSchedule={onBeforeDeleteSchedule}
onBeforeUpdateSchedule={onBeforeUpdateSchedule}></CalendarWithForwardedRef>
</div>
);
};
export default SchedulePage;
我不知道我做错了什么,但我一直收到这个错误
Unhandled Runtime Error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `__WEBPACK_DEFAULT_EXPORT__`.
Call Stack
createFiberFromTypeAndProps
node_modules\react-dom\cjs\react-dom.development.js (25058:0)
createFiberFromElement
node_modules\react-dom\cjs\react-dom.development.js (25086:0)
reconcileSingleElement
node_modules\react-dom\cjs\react-dom.development.js (14052:0)
reconcileChildFibers
node_modules\react-dom\cjs\react-dom.development.js (14112:0)
原来我的代码问题是由冲突的 npm 包引起的,我之前安装了 react-big-calendar 删除修复了问题