جافاسكريبت - Next.js: النافذة غير معرفة
أحاول استخدام apexcharts لتطبيق next.js ولكنه يعطيني خطأ يقول إن window غير معرف.
سأكون ممتنًا لأي مساعدة في ذلك.
هل يعرف أحد ما الذي يحدث ولماذا؟
import React from 'react';
import Chart from 'react-apexcharts';
export default class Graficos extends React.Component <{}, { options: any, series: any }> {
constructor(props:any) {
super(props);
this.state = {
options: {
chart: {
id: "basic-bar"
},
xaxis: {
categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999]
}
},
series: [
{
name: "series-1",
data: [30, 40, 45, 50, 49, 60, 70, 91]
}
]
};
}
render() {
return (
<div className="row">
<h1>Gráfico Básico</h1>
<div className="mixed-chart">
<Chart
options={this.state.options}
series={this.state.series}
type="bar"
width={500}
/>
</div>
</div>
);
}
}
الإجابة رقم 1
واحدة من الميزات الرئيسية لـ Next.js هي أنه يمكنه عرض أجزاء من تطبيق React الخاص بك على الخادم أو حتى في وقت البناء. بينما يمكن أن يكون هذا مفيدًا في تحسين أداء صفحتك، فإن الجانب السلبي هو أن الخادم لا يوفر جميع واجهات برمجة التطبيقات نفسها التي يمكن لتطبيقك الوصول إليها في المتصفح. في هذه الحالة، لا يوجد كائن window عالمي معرف.
لسوء الحظ، البحث في كود المصدر لـ apexcharts.js يظهر العديد من الإشارات إلى window: https://github.com/apexcharts/apexcharts.js/search?q=window. يحدث هذا أيضًا في الغلاف الخاص بهم لمكتبة React: https://github.com/apexcharts/react-apexcharts/blob/ecf67949df058e15db2bf244e8aa30d78fc8ee47/src/react-apexcharts.jsx#L5. بينما لا يبدو أن هناك طريقة لجعل apexcharts يتجنب الإشارات إلى window، يمكنك منع Next.js من استخدام الرسم البياني على الخادم. أبسط طريقة للقيام بذلك هي تغليف أي إشارة للكود بالتحقق مما إذا كان window معرفًا، على سبيل المثال.
<div className="mixed-chart">
{(typeof window !== 'undefined') &&
<Chart
options={this.state.options}
series={this.state.series}
type="bar"
width={500}
/>
}
</div>
مع apexcharts، ستحتاج أيضًا إلى القيام بذلك لاستيراد المكون لأن الاستيراد بمفرده سيؤدي إلى الإشارة إلى window كما هو موضح في الرابط الثاني. لتجاوز هذه المشكلة، ستحتاج إلى استخدام الاستيراد الديناميكي بدلاً من الاستيراد العادي الذي تستخدمه حاليًا: https://nextjs.org/docs/advanced-features/dynamic-import
import dynamic from 'next/dynamic'
const Chart = dynamic(() => import('react-apexcharts'), { ssr: false });
الإجابة رقم 2
واجهت مشكلة عدم تطابق النوع عند العمل مع الاستيرادات الديناميكية مع TypeScript لم تعمل معي في Next.js 13. ومع ذلك، قمت بحلها عن طريق إنشاء مكون جديد يسمى ApexChart.
في مكون ApexChart الجديد، قمت باستيراد مكتبة react-apexcharts وتمرير الخصائص المطلوبة إليها. إليك مثال على شكل المكون:
"use client";
import { useEffect, useState } from "react";
export default function ApexChart(props: any) {
const [Chart, setChart] = useState<any>();
const hasType = typeof props?.type !== "undefined";
useEffect(() => {
import("react-apexcharts").then((mod) => {
setChart(() => mod.default);
});
}, []);
return hasType && Chart && <Chart {...props} />;
}
