fullcalendar - NextJS - 动态导入不显示日历

时间:2021-03-22 16:35:35

标签: reactjs fullcalendar next.js fullcalendar-5 react-loadable

我正在使用 NextJS 和 Fullcalendar。

我尝试在 this example 中使用动态导入来使用 fullcalendar(有关详细信息,此示例解决方案来自 here)。

成功了,但是出现了问题。几乎每 5 次刷新尝试中就有 1 次以错误 Please import the top-level fullcalendar lib before attempting to import a plugin 结束(like this,但在我的情况下版本是正确的)

在那之后,我发现 next/dynamic 的模块选项已被弃用。我认为这是我的问题的根源(我不确定 100%,但至少它已被弃用并需要更新)。

正如 docs 所说,处理动态导入的新方法是这样的:

const DynamicComponent = dynamic(() =>
  import('../components/hello').then((mod) => mod.Hello)
)

但是因为我们需要多次导入,所以我找到了 this solution

目前,似乎一切正常,但我的代码无效。

import dynamic from "next/dynamic";
import { useEffect, useState } from "react";

import "@fullcalendar/common/main.css"; // @fullcalendar/react imports @fullcalendar/common
import "@fullcalendar/daygrid/main.css"; // @fullcalendar/timegrid imports @fullcalendar/daygrid
import "@fullcalendar/timegrid/main.css"; // @fullcalendar/timegrid is a direct import
import "./Fullcalendar.module.scss";
let CalendarComponent;

const Calendar = dynamic(() =>
  import("@fullcalendar/react").then((module) => module.Calendar)
);
const dayGridPlugin = dynamic(() =>
  import("@fullcalendar/daygrid").then((module) => module.dayGridPlugin)
);

export default function FullCalendar(props) {
  const [calendarLoaded, setCalendarLoaded] = useState(false);

  useEffect(() => {
    CalendarComponent = () => (
      <Calendar
        {...props}
        plugins={[dayGridPlugin]}
        initialView="dayGridMonth"
      />
    );
    setCalendarLoaded(true);
  }, []);

  let showCalendar = (props) => {
    if (!calendarLoaded) return <div>Loading ...</div>;
    return <CalendarComponent {...props} />;
  };

  return <div>{showCalendar(props)}</div>;
}

我还找到了另一种使用 next transpile modules 的方法。 但他们说"there is currently no way to transpile only parts of a package, it's all or nothing"

事实上,我在 next.config.js 中有一些东西。将这个文件编辑成转译模块是另一个神秘的冒险,充满了问题。

我该怎么办?

2 个答案:

答案 0 :(得分:1)

使 FullCalendar 与 Next.js 一起正常工作需要一些初始设置并对初始代码进行一些更改。

首先,让我们安装 next-transpile-modules 来处理 fullcalendar 的 ES 模块。确保包含您使用的所有 @fullcalendar 依赖项。

// next.config.js

const withTM = require('next-transpile-modules')([
  '@fullcalendar/common',
  '@fullcalendar/react',
  '@fullcalendar/daygrid'
]);

module.exports = withTM({
  // any other next.js settings here
});

接下来,添加自定义 Babel 配置以忽略 fullcalendar 中使用的 CSS 导入 - 需要安装 babel-plugin-transform-require-ignore 插件。这可以防止 Next.js 中的 Global CSS cannot be imported from within node_modules error

// babel.config.js

module.exports = {
    presets: [
        '@babel/preset-react'
    ],
    overrides: [
        {
            include: ['./node_modules'],
            plugins: [
                [
                    'babel-plugin-transform-require-ignore',
                    {
                        extensions: ['.css']
                    }
                 ]
            ]
        }
    ]
};

您必须在 fullcalendar 中包含 _app.js 的全局 CSS 以弥补这一点。全局 CSS 只能在 Next.js 中从此文件导入。

// _app.js

import '@fullcalendar/common/main.css'
import '@fullcalendar/daygrid/main.css'
import '@fullcalendar/timegrid/main.css'

最后,您可以简化和重构您的 FullCalendar 组件。这里不需要动态导入它的 fullcalendar 依赖项,我们会在使用时动态导入组件本身。

// components/FullCalendar.jsx

import Calendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';
import styles from './Fullcalendar.module.scss';

export default function FullCalendar(props) {
    return (
       <Calendar {...props} plugins={[dayGridPlugin]} initialView="dayGridMonth" />
    );
}

然后,在任何使用它的地方动态导入自定义组件。

import dynamic from 'next/dynamic';

const FullCalendar = dynamic(() => import('../components/FullCalendar'), {
    ssr: false
});

const SomePage = () => {
    return <FullCalendar />;
}

export default SomePage;

作为参考,这是基于 fullcalendar 中的 official example,进行了一些调整以使其适用于 next-transiple-modules v6.4.0。

答案 1 :(得分:0)


我们解决了这个问题


第一步:首先按照上面“juliomalves”的回答next.config.js。并在“_app.js”文件中导入CSS文件,同样按照上面的答案。


第 2 步:像我们在 react js 中编写的那样编写所有完整的日历代码,但使其成为一个单独的组件。


第 3 步:接下来使用 NextJS 动态导入导入“日历”组件。


import dynamic from 'next/dynamic';

const Calendar = dynamic(()=> import('../path/to/component/Calendar'),{ssr:false})

它现在应该可以工作了!