Next.js+TypeScript动态渲染Leaflet组件报错求助
问题场景
在Next.js的TypeScript环境中渲染Leaflet地图,已通过dynamic禁用SSR避免window not defined问题,但出现以下报错:
组件代码
import React from "react"; import { MapContainer, TileLayer } from "react-leaflet"; export const Leaflet: React.FC = () => { return ( <MapContainer center={{ lat: 48.71291, lng: 44.52693 }} zoom={13}> <TileLayer attribution='© <a href="http://osm.org/copyright%22%3EOpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> </MapContainer> ); };
动态渲染代码
const Home: NextPage = () => { const MapWithNoSSR = dynamic(() => import("../components/Leaflet"), { ssr: false, }); return ( <> <MapWithNoSSR/> </> ); }; export default Home
报错信息
TypeScript报错:
Argument of type '() => Promise<typeof import("/src/components/Leaflet")>' is not assignable to parameter of type 'DynamicOptions<{}> | Loader<{}>'. Type '() => Promise<typeof import("/src/components/Leaflet")>' is not assignable to type '() => LoaderComponent<{}>'.
浏览器报错:
Error: Element type is invalid. Received a promise that resolves to: [object Module]. Lazy element type must resolve to a class or function.
解决方法
核心原因是Next.js的dynamic默认期望导入默认导出的组件,但当前Leaflet组件是命名导出,两种修复方式:
方式一:将组件改为默认导出
修改Leaflet组件文件,把命名导出改为默认导出:
import React from "react"; import { MapContainer, TileLayer } from "react-leaflet"; const Leaflet: React.FC = () => { return ( <MapContainer center={{ lat: 48.71291, lng: 44.52693 }} zoom={13}> <TileLayer attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> </MapContainer> ); }; export default Leaflet;
注:已修正原代码中TileLayer attribution链接的语法错误
方式二:动态导入时指定命名导出
保留组件的命名导出,修改动态导入逻辑,明确返回命名导出的组件:
const Home: NextPage = () => { const MapWithNoSSR = dynamic(() => import("../components/Leaflet").then((mod) => mod.Leaflet), { ssr: false } ); return ( <> <MapWithNoSSR/> </> ); }; export default Home
内容的提问来源于stack exchange,提问作者peternovak

