You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用esm.run CDN+importmap引入React18时出现useEffect读取错误求助

问题:使用esm.run CDN + Importmap导入React时出现useEffect读取null错误

我在用jsdelivr支持的ES模块CDN——esm.run,想直接从远程CDN导入React。通过importmap,浏览器应该把import React from 'react'转换成import React from 'https://esm.run/react@18',但运行代码时出现错误:TypeError: Cannot read properties of null (reading 'useEffect'),求解决。


完整代码

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <div id="root"></div>
        <script type="importmap">
            {
                "imports": {
                    "react": "https://esm.run/react@18",
                    "react-dom": "https://esm.run/react-dom@18"
                }
            }
        </script>
        <script src="/dist/index.js" type="module"></script>
    </body>
</html>

/dist/index.js (打包后)

(function(){"use strict";try{if(typeof document!="undefined"){var e=document.createElement("style");e.appendChild(document.createTextNode("")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})();
import require$$0 from "react";
import ReactDom from "react-dom";
var jsxRuntimeExports = {};
var jsxRuntime = {
  get exports() {
    return jsxRuntimeExports;
  },
  set exports(v) {
    jsxRuntimeExports = v;
  }
};
var reactJsxRuntime_production_min = {};
/**
 * @license React
 * react-jsx-runtime.production.min.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
var f = require$$0, k = Symbol.for("react.element"), l = Symbol.for("react.fragment"), m = Object.prototype.hasOwnProperty, n = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p = { key: true, ref: true, __self: true, __source: true };
function q(c, a, g) {
  var b, d = {}, e = null, h = null;
  void 0 !== g && (e = "" + g);
  void 0 !== a.key && (e = "" + a.key);
  void 0 !== a.ref && (h = a.ref);
  for (b in a)
    m.call(a, b) && !p.hasOwnProperty(b) && (d[b] = a[b]);
  if (c && c.defaultProps)
    for (b in a = c.defaultProps, a)
      void 0 === d[b] && (d[b] = a[b]);
  return { $$typeof: k, type: c, key: e, ref: h, props: d, _owner: n.current };
}
reactJsxRuntime_production_min.Fragment = l;
reactJsxRuntime_production_min.jsx = q;
reactJsxRuntime_production_min.jsxs = q;
(function(module) {
  {
    module.exports = reactJsxRuntime_production_min;
  }
})(jsxRuntime);
const jsx = jsxRuntimeExports.jsx;
const App = () => {
  require$$0.useEffect(() => {
    console.log("我是demo");
  }, []);
  return /* @__PURE__ */ jsx("div", { children: "我是demo rendssder" });
};
ReactDom.render(/* @__PURE__ */ jsx(App, {}), document.getElementById("root"));
export {
  App as default
};

解决方案

核心原因

错误源于React 18 ESM模块的导出结构与代码导入方式不匹配:

  • React 18的ESM构建中,useEffect等钩子是命名导出,并非挂载在默认导出对象上;
  • 代码中手动实现了JSX Runtime,和React官方的导出逻辑冲突,导致require$$0(即默认导出)无法正确获取React内部属性,最终出现null读取错误。

修复步骤

  1. 调整Importmap配置
    明确指定需要的导出项,确保esm.run返回正确的导出结构:

    <script type="importmap">
        {
            "imports": {
                "react": "https://esm.run/react@18?exports=default,useEffect",
                "react-dom/client": "https://esm.run/react-dom@18/client?exports=default"
            }
        }
    </script>
    

    通过?exports=参数指定default和useEffect,保证能正确导入所需API。

  2. 修改导入与渲染逻辑
    直接导入命名导出的钩子,同时改用React 18推荐的createRoot渲染方式:

    import React, { useEffect } from "react";
    import { createRoot } from "react-dom/client";
    
    const App = () => {
      useEffect(() => {
        console.log("我是demo");
      }, []);
      return <div>我是demo renderer</div>;
    };
    
    const root = createRoot(document.getElementById("root"));
    root.render(<App />);
    
  3. 移除手动JSX Runtime代码
    代码中打包的自定义JSX Runtime会干扰React的正常导出,直接删除这部分逻辑,依赖CDN提供的React环境即可。

  4. 优化打包配置
    若使用Vite等工具打包,需关闭自动注入JSX Runtime的配置,避免打包时混入多余代码,确保完全依赖CDN提供的React模块。


内容的提问来源于stack exchange,提问作者Hanwen D.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:31:23