如何在React中使用import()动态加载组件?

4

我尝试使用import()来动态加载组件,但是没有成功。相比之下,React.lazy似乎更加可靠。

App.js

import React, { useState } from 'react';
function App() {
  const [Com, setCom] = useState(null);

  const handleClick = () => {
      import("./A.js").then(c => {
        //console.log(c.default)
        setCom(c.default)
      }) 
  }

  return (
      <div>
        <button onClick={handleClick}>Load</button>
        { Com ? <Com /> : null }
      </div>
   );
}

export default App;

A.js

import React from "react";

export default function A () {
    return (<div>A</div>)
}

错误:元素类型无效:应该是字符串(用于内置组件)或类/函数(用于复合组件),但却是:对象。

实际上,我打印出了 c.default。它确实是一个函数。

c.default

ƒ A() {
  return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
    __source: {
      fileName: _jsxFileName,
      lineNumber: 4
    },
    __self: this
  }, "A");
}
2个回答

4

实际上,这与动态 import 无关,而是与 useState 实现有关。例如:

import Comp from "./A";

function App() {
  const [Com, setCom] = useState(Comp);

  return (
    <div>
      <Com />
    </div>
  );
}

会产生相同的错误。这是因为当您调用 useState(Comp) 时,Comp "function"(即组件)被执行了(您可以通过将代码中的任何 <Com /> 删除并在 A 中添加 console.log 进行测试。控制台日志仍将出现)。
因此,Com 不再是组件,而是 JSX 元素。当您尝试以函数方式呈现 JSX 元素(即用 </> 包装它时,会抛出此错误。
解决方案要么将 Com 设置为组件形式(() => Com),要么将其作为 JSX 子元素进行渲染({Com})。
import React, { useState } from "react";

function App() {
  const [Com, setCom] = useState(null);

  const handleClick = () => {
    import("./A.js").then(c => {
      //console.log(c.default)
      setCom(c.default);
    });
  };

  return (
    <div>
      <button onClick={handleClick}>Load</button>
      {/* <Comp /> */}
      {Com}
    </div>
  );
}

export default App;

点击此处可查看与import Comp from "./A";useState(Comp)的原始结果对比,可通过使用console.dir命令进行。

顺便提一下,在这里你可以看到不同之处。

import Comp from "./A";

function App() {
  const [Com, setCom] = useState(Comp);
  // console.log(1, Com, 2, Comp);
  console.dir(Com) // Object
  console.dir(Comp) // ƒ A()
  //...
}

其实我认为React的延迟加载很不错。据我记得,它只在需要时才渲染,并且已经给你返回了可渲染组件。 - TalOrlanczyk

3

如果使用函数调用setState,那么它会将先前的状态作为参数执行。

const [count,setCount] = useState(0)
setCount(prevCount => prevCount + 1)

在你的情况下,React 不会使用导入的函数来更新状态,而是执行该函数并将结果作为状态设置。
解决方案:
setCom(() => c.default)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接