【问题标题】:Not defined error when attempting to dynamically load scripts with React.js尝试使用 React.js 动态加载脚本时未定义错误
【发布时间】:2021-01-22 14:32:19
【问题描述】:

对于我正在进行的项目,我制作了一个 React 应用程序,该应用程序基于在单击某个国家/地区时显示信息。我正在使用来自 simplemaps.com (https://simplemaps.com/custom/world) 的 SVG 世界地图,它带有 javascript 挂钩来处理用户点击,例如

<script type="text/javascript"> 
   simplemaps_worldmap.hooks.click_state = function(id){
     alert(simplemaps_worldmap_mapdata.state_specific[id].name);
   }
</script>

为了显示地图,您还必须包含

<script src="./scripts/mapdata.js"></script>
<script src="./scripts/worldmap.js"></script>

<div id="map"></div>

渲染 div 组件由我制作的 React 组件处理,但这意味着当我单击另一个页面并单击返回时地图停止显示。为了解决这个问题,我开始动态加载脚本作为 React 组件的一部分,如下所示:

import React, {useEffect} from 'react';

function Map() {
    useEffect(() => {
        const mapScript = document.createElement('script');
        const worldScript = document.createElement('script');
        const clickScript = document.createElement('script');
    
        mapScript.type = 'text/javascript';
        mapScript.src = '../scripts/mapdata.js';

        worldScript.type = 'text/javascript';
        worldScript.src = '../scripts/worldmap.js';

        clickScript.type = "text/javascript";
        clickScript.innerHTML = `simplemaps_worldmap.hooks.click_state = function(id){
            alert(simplemaps_worldmap_mapdata.state_specific[id].name);
        }`;
    
        document.head.appendChild(mapScript);
        document.head.appendChild(worldScript);
        document.body.appendChild(clickScript);
    
        return () => {
            document.head.removeChild(mapScript);
            document.head.removeChild(worldScript);
            document.body.removeChild(clickScript);
        }
    }, []);

    return (
        <div id="map">
        </div>
    )
}

export default Map;

最初它有效,但在我添加了 clickScript 行之后:

const clickScript = document.createElement('script');

clickScript.type = "text/javascript";
clickScript.innerHTML = `simplemaps_worldmap.hooks.click_state = function(id){
    alert(simplemaps_worldmap_mapdata.state_specific[id].name);
};`

document.body.appendChild(clickScript);
    
return () => {
    document.body.removeChild(clickScript);
}

我开始收到错误:ReferenceError: simplemaps_worldmap is not defined。 它在 HTML 页面中加载时按预期工作,如下所示:

<script src="./scripts/mapdata.js"></script>
<script src="./scripts/worldmap.js"></script>
<script type="text/javascript"> 
   simplemaps_worldmap.hooks.click_state = function(id){
     alert(simplemaps_worldmap_mapdata.state_specific[id].name);
   }
</script>

但是,当它被动态加载时,它似乎会破坏它。我已经尝试将它们加载到头部和身体中,但似乎没有任何区别。

总结问题:脚本在 HTML 中运行良好,但在 javascript 中加载时 clickScript 似乎无法找到 mapData.js 来引用它,即使 worldData.js 可以找到 mapData.js。我尝试将 clickScript 设为外部,但这似乎无法解决问题。

如果这是一个明显的解决方法,我们深表歉意,但我们将不胜感激。

编辑:My index.htmlMy map.js

【问题讨论】:

  • “当我点击不同的页面并点击返回时” - 点击返回是什么意思?是正在重新加载页面,还是单页应用程序?
  • @RichardHunter 这是一个单页应用程序,我使用 react router dom 在“页面”之间导航。当我单击另一个“页面”并单击返回时,地图不会呈现。如果我刷新网页,它会呈现,但我一直在努力避免这种情况,使其看起来无缝。
  • 如果我理解正确,SimpleMaps 脚本在页面加载时会查找 id="map" 元素并将地图呈现到其中。但是当您重新渲染组件时,它当然会被删除(因为您正在渲染一个空的 div)。所以你真正想做的是强制 SimpleMaps 重新初始化。重新加载脚本是不必要的,因为它们已经存在。简单地图没有重新初始化的方法吗?
  • 我在文档中看到了一个simplemaps_worldmap.load() 方法。 simplemaps.com/docs/api 。你可以在 useEffect() 钩子里试试。
  • 这也可能有用。手动加载地图而不是让 SimpleMap 处理事情可能是个好主意。 simplemaps.com/docs/load-manually

标签: javascript html reactjs svg


【解决方案1】:

SimpleMaps 脚本在页面加载后查找id="map" 元素并将地图呈现到其中。当您重新渲染组件时,地图会被删除(因为您正在渲染一个空的 div)。所以真的,你想要做的是强制 SimpleMaps 重新初始化地图。无需重新加载脚本,因为它们已经存在。

我无法创建工作版本,因为我没有 SimpleMaps 的许可证,但这是我可能采用的方法,基于我在 docs 中阅读的关于手动加载的内容。

在 mapdata.js 中

main_settings.auto_load='no';

在 React 组件中:

import React, {useEffect} from 'react';

function Map() {

    useEffect(() => {
      
      simplemaps_worldmap.load();

    }, []);

    return (
        <div id="map"></div>
    )
}

export default Map;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 2021-03-12
    • 1970-01-01
    • 1970-01-01
    • 2020-12-31
    相关资源
    最近更新 更多