我目前正在建立一个使用传单包的网站。但是,这个包需要窗口对象。这就是为什么我要导入一个用传单制作的组件,作为关闭ssr的动态组件。就像这样:
import dynamic from "next/dynamic";
const MapWithNoSSR = dynamic(() => import("../../map"), {
ssr: false
});
export default function faqOnly(props){
...
return (<> <MapWithNoSSR /></>)
}Map组件如下所示:
import React, { useEffect, useState, useRef } from "react";
import { OpenStreetMapProvider } from 'leaflet-geosearch';
import "leaflet/dist/leaflet.css";
import 'leaflet/dist/leaflet.css'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css'
import "leaflet-defaulticon-compatibility";
import dynamic from "next/dynamic";
const L = dynamic(() => import("leaflet"), {
ssr: false,
suspense: true,
loading: () => <p>...</p>
});
function Map(props) {
useEffect(async () => {
if(window === undefined) return
const provider = new OpenStreetMapProvider();
const results = await provider.search({ query: props.adress });
if(results.length > 0 == true){
var map = L.map('map', {
center: [results[0].y, results[0].x],
zoom: 18,
layers: [
L.tileLayer('https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png', {
attribution: ''
}),
]
})
L.marker([results[0].y, results[0].x]).addTo(map)
}else{
document.getElementById("map").style.display = "none"
}
}, [])
return <div id="map" style={{ height: "30vh"}}></div>
}
export default Map;当我运行npm run build时,我会得到这个错误
ReferenceError: window is not defined
at E:\Github\Planer\rl-planer\node_modules\leaflet\dist\leaflet-src.js:230:19
at E:\Github\Planer\rl-planer\node_modules\leaflet\dist\leaflet-src.js:7:66
at Object.<anonymous> (E:\Github\Planer\rl-planer\node_modules\leaflet\dist\leaflet-src.js:10:3)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (E:\Github\Planer\rl-planer\node_modules\leaflet-geosearch\dist\geosearch.js:1:7) {
type: 'ReferenceError'
}这在开发中很好,但是当我尝试构建这个项目(下一个构建)时,它会在传单包中抛出一个“窗口未定义”错误,这是我在开发模式下处理它之前从未做过的。
我在这里查看了其他问题,但似乎将动态导入移出组件之外,为每个人(除了我)修复了它。我只是很蠢还是这里有什么问题?
发布于 2022-05-06 22:39:10
也许您根本不需要next/dynamic,只需在useEffect函数体中使用简单js动态导入即可。
(useEffect只在客户端上运行)
Nextjs有一个看起来非常相似的例子:https://nextjs.org/docs/advanced-features/dynamic-import。(第一个在页面上使用fuse.js)
import React, { useEffect, useState, useRef } from "react";
import { OpenStreetMapProvider } from 'leaflet-geosearch';
import "leaflet/dist/leaflet.css";
import 'leaflet/dist/leaflet.css'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css'
import "leaflet-defaulticon-compatibility";
function Map(props) {
useEffect(async () => {
const L = await import("leaflet")
const provider = new OpenStreetMapProvider();
const results = await provider.search({ query: props.adress });
if(results.length > 0 == true) {
var map = L.map('map', {
center: [results[0].y, results[0].x],
zoom: 18,
layers:
[
L.tileLayer(
'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png',
{ attribution: ''}
),
]
})
L.marker([results[0].y, results[0].x]).addTo(map)
} else {
document.getElementById("map").style.display = "none"
}
}, [])
return <div id="map" style={{ height: "30vh"}}></div>
}
export default Map;已更新
好吧,所以,尝试移动所有需要useEffect钩子窗口的js有点麻烦。只导入整个组件客户端就更容易了。在我看来,您的示例代码看起来不错--除了您再次在地图文件中动态导入传单之外:
page.jsx
import dynamic from "next/dynamic";
const MapWithNoSSR = dynamic(() =>
import("../../map"), { ssr: false });
export default function faqOnly(props){
...
return <MapWithNoSSR />
}map.jsx
import React, { useEffect, useState, useRef } from "react";
import { OpenStreetMapProvider } from 'leaflet-geosearch';
import L from 'leaflet'
import "leaflet/dist/leaflet.css";
import 'leaflet/dist/leaflet.css'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css'
import "leaflet-defaulticon-compatibility";
function Map(props) {
useEffect(async () => {
const provider = new OpenStreetMapProvider();
const results = await provider.search({ query: props.adress });
if(results.length > 0 == true) {
var map = L.map('map', {
center: [results[0].y, results[0].x],
zoom: 18,
layers:
[
L.tileLayer(
'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png',
{ attribution: ''}
),
]
})
L.marker([results[0].y, results[0].x]).addTo(map)
} else {
document.getElementById("map").style.display = "none"
}
}, [])
return <div id="map" style={{ height: "30vh"}}></div>
}
export default Map;https://stackoverflow.com/questions/72133970
复制相似问题