基于Arco框架 gaode

文章介绍了在NextJS项目中使用高德地图遇到的问题及解决方案,包括因服务器端渲染(SSR)导致的windowisundefined错误,通过dynamic导入解决,以及Mock对地图请求的干扰和处理跨域问题。最后提到了在打包时遇到的问题和在useEffect中处理依赖的策略。
摘要由CSDN通过智能技术生成

总结:① nextjs基于服务器加载的策略,如果是组件的话建议使用动态加载的方式执行,如果是函数的话可以直接写入useEffect。

② mock对地图请求会有拦截等问题,建议直接关闭。

找刺激打算体验nextjs。arco在支持nextjs比较稳定,整个过程体验良好,不过项目中用到高德地图的时候出现了问题。跳坑解决方案如下:

① 无法加载地图,提示 window is undefined

解:官方指示react在componentDidMount之前不会得到window,在页面渲染到浏览器后,才能找到window。由于Nextjs属于服务器渲染,只能采用禁用ssr模式。

import dynamic from 'next/dynamic'
const Gaode = dynamic(() => import('@/pages/map/gaode'), {
  ssr: false,
})

...
<Gaode options={mapOptions}></Gaode>

② 地图框加载出来,但是地图数据没有。console 有跨域提醒。

答:仔细对比另外成功的网页响应,发现部分网络请求携带cookie。全局搜withCredentials,果然在mock.user.ts中找到了罪魁祸首。

Mock.XHR.prototype.withCredentials = true

直接删除。

③ 网络通信无问题,但是地图还是没有显示。

答:直接删除Mock,恢复正常。

④ 开发正常,但是通过next build打包出现问题,提示window is not defined

答:感谢高手,原文如下reactjs 关闭服务器端呈现的Next.js动态导入在生产构建上不起作用 _大数据知识库 (saoniuhuo.com)也许你根本不需要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有点麻烦。只导入整个组件客户端更容易。对我来说,你的示例代码看起来不错--除了你在map文件中再次动态导入leaflet这一事实:


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;


======================下面是不断尝试过程 =====================

尝试1:依旧报错。

在config中加入withTM = require('next-transpile-modules')([

'@amap/amap-jsapi-loader'

],

尝试2

xxxxxx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值