Chartjs plugin zoom引用错误:窗口未定义

6jjcrrmo  于 2024-01-07  发布在  Chart.js
关注(0)|答案(2)|浏览(184)

在Nextjs应用程序中,当我运行构建和导出命令时,出现了ReferenceError
我已经附上截图供您参考..
当从项目中删除chartjs-plugin-zoom的导入时,构建和导出工作正常。. x1c 0d1x

qnzebej0

qnzebej01#

这是因为nextjs默认使用服务器端渲染。zoom-plugin需要window对象,但由于组件在节点上渲染,因此无法使用。
要制作依赖于浏览器API的工作组件,可以使用next/dynamic导入

chart-with-zoom.jsx

import zoomPlugin from 'chartjs-plugin-zoom'; // require window in order to be imported

ChartJS.register(zoomPlugin)

export default function ChartZoom() {
...

字符集

app.jsx

import dynamic from 'next/dynamic';

const ChartZoom = dynamic(() => import('PATH TO chart-with-zoom'), {
  ssr: false, // Disable server-side rendering
});

...
return <ChartZoom />


或者在组件的开头使用'use client'关键字

c7rzv4ha

c7rzv4ha2#

所以我绞尽脑汁之后找到了解决这个问题的办法。
假设你要在page.tsx中导入“chartjs-plugin-zoom”,然后将所有代码移动到一个组件名称中,让我们调用pageentA.tsx,然后在page.tsx中动态导入这个组件,并使用NoSSR组件 Package 它。示例代码Page.tsx

"use client";
import React from "react";
import NoSSR from "./components/NoSSR";
import dynamic from "next/dynamic";
const ComponentA = dynamic(() => import("./components/ComponentA"), {
    ssr: true,
});

const Page = () => {
    return (
        <NoSSR>
            <ComponentA />
        </NoSSR>
    );
};

export default Page;

字符集

NoSSR.tsx

import * as React from "react";

const useEnhancedEffect =
    typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;

type Props = {
    defer?: boolean;
    fallback?: JSX.Element;
    children: React.ReactNode;
};
/**
 * NoSSR purposely removes components from the subject of Server Side Rendering (SSR).
 *
 * This component can be useful in a variety of situations:
 * - Escape hatch for broken dependencies not supporting SSR.
 * - Improve the time-to-first paint on the client by only rendering above the fold.
 * - Reduce the rendering time on the server.
 * - Under too heavy server load, you can turn on service degradation.
 */
function NoSSR(props: Props) {
    const { children, defer = false, fallback = null } = props;
    const [mountedState, setMountedState] = React.useState(false);

    useEnhancedEffect(() => {
        if (!defer) {
            setMountedState(true);
        }
    }, [defer]);

    React.useEffect(() => {
        if (defer) {
            setMountedState(true);
        }
    }, [defer]);

    // eslint-disable-next-line react/jsx-no-useless-fragment
    return <>{mountedState ? children : fallback}</>;
}

export default NoSSR;

相关问题