React中如何使用import()动态加载组件?
How to use import () to dynamically load components in React?
我尝试用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>)
}
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
其实我打印出来了c.default
。真是个函数
c.default
ƒ A() {
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
__source: {
fileName: _jsxFileName,
lineNumber: 4
},
__self: this
}, "A");
}
如果用函数调用setState,它将以先前的值作为参数执行。
const [count,setCount] = useState(0)
setCount(prevCount => prevCount + 1)
在您的情况下,React 不会使用导入的函数更新状态,而是会执行它并将结果设置为状态。
解决方案:
setCom(() => c.default)
实际上,它与动态 import
无关,而与 useState
实施有关。例如:
import Comp from "./A";
function App() {
const [Com, setCom] = useState(Comp);
return (
<div>
<Com />
</div>
);
}
会抛出同样的错误。那是因为当您调用 useState(Comp)
、Comp
"function"(即组件)时(您可以测试它从代码中删除任何 <Com />
,添加 console.log
里面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;
https://codesandbox.io/s/answer-for-httpsWhosebugcomq62125854863110-jj2wu
顺便说一句,你可以 see the difference 通过 console.dir
import Comp from "./A";
的原始结果和 useState(Comp)
的结果
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()
//...
}
我尝试用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>)
}
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
其实我打印出来了c.default
。真是个函数
c.default
ƒ A() {
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
__source: {
fileName: _jsxFileName,
lineNumber: 4
},
__self: this
}, "A");
}
如果用函数调用setState,它将以先前的值作为参数执行。
const [count,setCount] = useState(0)
setCount(prevCount => prevCount + 1)
在您的情况下,React 不会使用导入的函数更新状态,而是会执行它并将结果设置为状态。
解决方案:
setCom(() => c.default)
实际上,它与动态 import
无关,而与 useState
实施有关。例如:
import Comp from "./A";
function App() {
const [Com, setCom] = useState(Comp);
return (
<div>
<Com />
</div>
);
}
会抛出同样的错误。那是因为当您调用 useState(Comp)
、Comp
"function"(即组件)时(您可以测试它从代码中删除任何 <Com />
,添加 console.log
里面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;
https://codesandbox.io/s/answer-for-httpsWhosebugcomq62125854863110-jj2wu
顺便说一句,你可以 see the difference 通过 console.dir
import Comp from "./A";
的原始结果和 useState(Comp)
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()
//...
}