React-leaflet 自定义组件-未传递上下文?

Set*_*ske 5 custom-component reactjs webpack react-leaflet

我正在为 react-leaflet 编写一个自定义组件。它是一个可编辑的弹出窗口,还有一些其他功能。 这里是一个例子的代码和。组件的源代码在这里。这个例子只是做了一个import EditablePopup from 'my-react-leaflet-popup-plugin',它是我项目中的一个 .js 文件。效果很好。

我正在尝试使用 webpack 将其打包为一个节点模块,以便其他人可以使用它。它编译没有问题。你可以在这里看到我的 webpack.config.js 。然后我使用npm link将这个模块链接到我本地机器上的一个测试项目。当我这样做时,我收到错误消息:

TypeError: Cannot read property 'leafletElement' of null

  460 |   value: function value() {
  461 |     var e = this;
  462 |     this.props.open && setTimeout(function () {
> 463 |       e.thePopup.leafletElement._source.openPopup();
      | ^  464 |     }, .001);
  465 |   }
  466 | }, {
Run Code Online (Sandbox Code Playgroud)

即使我摆脱了那个条款,我也会得到这个:

TypeError: Cannot read property 'openPopup' of undefined


  9226 | // @method openOn(map: Map): this
  9227 | // Adds the popup to the map and closes the previous one. The same as `map.openPopup(popup)`.
  9228 | openOn: function openOn(map) {
> 9229 |   map.openPopup(this);
       | ^  9230 |   return this;
  9231 | },
  9232 | onAdd: function onAdd(map) {
Run Code Online (Sandbox Code Playgroud)

它就像弹出窗口试图将自己添加到地图,但没有找到父地图组件的地图实例。我的预感是,由于某种原因,当使用 webpack 构建它并将其作为 npm 模块导入时,react-leaflet 地图的上下文没有正确传递给我的组件。我不太明白,因为我的组件只是 react-leaflet<Popup>组件的一个装扮版本。我<EditablePopup>使用<Popup>的直接孩子,这本来应该收到LeafletConsumer背景下的消费包装。

我不确定为什么这个组件在我的项目中链接时效果很好,但是当通过 webpack 构建并通过 npm 导入时会出现这个错误。

小智 5

我在工作场所也遇到了类似的问题,我现在怀疑我们声明 webpack 配置的(类似)方式是罪魁祸首。但对我来说,仅更改libraryTarget 没有任何效果。在描述我们的设置后,我的见解如下......

我们有一组可视化组件,我们将其捆绑到一个“库”中,并将其导入到主项目中。主项目需要获取一些外部数据,但需要在整个库组件的任意位置使用。我们不想到处传递道具。那么上下文,对吧?除非提供者(我们在“主”项目中设置和初始化)和使用者位于库边界的不同侧,否则使用者的上下文始终是未定义的(或者更确切地说,无论“createContext”的默认值是什么...我们没有使用初始化器)。

不管怎样,快进一堆。如果我将库中的每个不同组件作为其自己的独立“条目”(在 webpack 文件中)列出,改为构建一个导入并重新导出所有内容的 index.js 文件 - 并且只包含该一个文件作为单个文件“entry”(在 webpack 中)——然后事情就开始工作了。

因为 React context API 需要共享创建的 Context 对象,但共享的概念(无论如何我猜)是在模块级别。它一定不是真正的全球性的。所以不同的入口点、不同的模块、不同的上下文对象。消费者被冷落了。


Set*_*ske 2

我正在发布一个答案,该答案的灵感来自于Cannot read property 'Component' of undefined - webpack build of React component plugin。我在这里的问题似乎至少在某种程度上与React Context API notworking from custom NPM component library 问题有关,那些人仍在寻找答案 - 也许这会有所帮助。

我必须做出调整webpack.config.js才能package.json解决这个问题。


webpack.config.js

改变这个:

  libraryTarget: 'commonjs2'
Run Code Online (Sandbox Code Playgroud)

对此:


      library: "EditablePopup",
      libraryTarget: 'umd'

Run Code Online (Sandbox Code Playgroud)

以及添加mode: developmentmodule.exports.


package.json

将我的一些移动dependenciespeerDependencies


    // Change from this:
      "dependencies": {
        "html-react-parser": "^0.10.0",
        "leaflet": "^1.6.0",
        "react": "^16.12.0",
        "react-contenteditable": "^3.3.3",
        "react-dom": "^16.12.0",
        "react-leaflet": "^2.6.1",
        "webpack": "^4.41.5"
      },
      "peerDependencies": {
        "react": "^16.12.0",
        "react-dom": "^16.12.0",
        "react-leaflet": "^2.6.1",
        "leaflet": "^1.6.0"
      }

    // to this:
      "dependencies": {
        "html-react-parser": "^0.10.0",
        "react-contenteditable": "^3.3.3",
        "webpack": "^4.41.5"
      },
      "peerDependencies": {
        "react": "^16.12.0",
        "react-dom": "^16.12.0",
        "react-leaflet": "^2.6.1",
        "leaflet": "^1.6.0"
      }

Run Code Online (Sandbox Code Playgroud)

我很确定这些webpack.config.js变化才是最重要的。为了完整起见,以下是对该文件的更改:

    // webpack.config.js

    var 路径 = require('路径');
    模块. 导出 = {
        条目:'./src/EditablePopup.js',
        输出: {
            路径:path.resolve(__dirname, 'build'),
            文件名:'EditablePopup.js',
    -       库目标:'commonjs2',
    + 库:“EditablePopup”,
    + 库目标:'umd'
        },
    +模式:“开发”,
        模块: {
            规则:[
                {
                    测试:/\.js$/,
                    包括:path.resolve(__dirname, 'src'),
                    排除:/(node_modules|bower_components|build)/,
                    使用: [
                        {
                            加载器:'巴别塔加载器',
                            选项: {
                                预设:['@babel/preset-env']
                            }
                        }
                    ]
                },
                {
                    测试:/\.css$/,
                    使用: [
                        { 加载器:'样式加载器'},
                        { 加载器:'css-loader' }
                    ]  
                }
            ]
        },
        外部:{
            'react-dom': 'commonjs React-dom',
            传单:{
                commonjs: '传单',
                commonjs2: '传单',
                根:'L'
            },
            '反应传单':{
                commonjs: '反应传单',
                commonjs2: '反应传单',
                根:'ReactLeaflet'
            },
            反应:{
                commonjs: '反应',
                commonjs2: '反应',
                根:“反应”
            }
        }
    };