通过变量动态导入文件 - 本机反应
import file dynamically by variable - react native
我有一个 path.json 包含组件路径的文件
// path.json
{
"main": "./login/index.js",
"paths": [
{
"name": "login",
"path": "./login/index.js",
"image": ""
}
]
}
我想在 React Native 中动态加载 './login/index.js' 文件并渲染这个特定文件
我目前的实现
const MyComponent = createLazyContainer(() => {
const componentPath = PathJson.main; // ./login/index.js
return import(`${componentPath}`); //import error here @ line 7
});
export default MyComponent;
我收到以下错误:
Invalid call at line 7: import("" + componentPath)
在 React Native 中,所有导入的文件都捆绑在一起,只有那些文件可以动态导入。
假设您有三个文件 index.js
、test_1.js
和 test_2.js
,如果您只在 index.js
中导入了 test_1.js
,那么 React Native 只会捆绑这两个文件,留下 test_2.js
.
所以要回答你的问题,即使动态导入在 React Native 中有效,但因为这些文件不是包的一部分,你无法导入它们。
人们在讨论帖中告诉您的是正确的,但我想添加一个可能的解决方案。所有 imports/require 都在编译时解析,而不是在您尝试执行的 运行 时解析。当您 运行 您的应用程序时,如果您尚未导入文件,则无法使用它们。
有一个变通方法,假设您事先知道所有文件,即执行类似于工厂的操作:
const possiblePaths = {
'one': require('path/to/file/1),
'two': require('path/to/file/2)
}
funtion(type){
return possiblePaths[type]
}
然后你可以像这样使用它:
render(){
const MyComponent = function('one')
return <MyComponent/>
}
这或多或少是伪代码,我不能马上工作,但希望你明白了。您需要存储对每个可能需要的导入的引用,然后不要使用导入,使用在编译时为您创建的引用。
我曾经遇到过类似的情况,我需要通过变量进行导入,但那是 仅限于在组件内部导入组件 并且它 使用代码拆分(编辑:我正在寻找不依赖代码拆分的解决方案,我刚刚意识到问题中有一个 react-native 标签,我不认为代码-splitting 在 RN 中是一个不错的选择)。我不确定我的方法能为您提供多少帮助,但就这样吧。
旁注:
- 导入包含
index.js(jsx|ts|tsx)
文件的文件夹应自动解析为该 index
文件。
- 从
from './login/index.js'
导入通常会引发 'Module not found' 错误。导入 from './login/index'
或 from './login
但我更喜欢最后一个,因为它最短且最简单。
在path.json
中:
{
"main": "./login", // '.js' is removed
"paths": [
{
"name": "login",
"path": "./login/index.js", // Not sure what this is for, but if necessary, remove the '.js' here as well
"image": ""
}
]
}
在MyComponent.js
:
import React, { lazy, Suspense } from 'react'
import PathJson from './path'
// 1. We need a UI to show while component is being loaded
const Loader = () => <div>{'Loading...'}</div>
// 2. We need a fallback UI if component is not found
const DocUnavailable = () => <div>{'We\'re sorry, but this document is unavailable.'}</div>
// 3. Create a resolver function ('resolver' is just a name I give)
function resolveImport(pathToComponent, FallbackComponent) {
let componentFound = false
let RenderComponent = () => <FallbackComponent /> // Assign fallback first
try {
if (require.resolve(pathToComponent)) {
componentFound = true
}
} catch (e) { } // Kinda hacky, if you don't mind, but it works
if (componentFound) {
// If found, replace fallback with the valid component
RenderComponent = lazy(() => import(pathToComponent))
}
return RenderComponent
}
// 4. Finally, implement it in a component
class MyComponent extends React.Component {
render() {
const componentPath = PathJson.main
const RenderComponent = resolveImport(componentPath, DocUnavailable)
return (
<Suspense fallback={<Loader />}>
<RenderComponent />
</Suspense>
)
}
}
export default MyComponent
参考文献:
- 'resolver' 函数的实现 based on Langutil
- 代码拆分
lazy
& Suspense
based on React Docs
实际上,React Native 开发问题不像 Web 的开发。
正因如此,在react-native项目的制作中lazy加载根本不是那么重要。只需导入您想要的任何内容,然后在项目的任何文件中使用它们。所有这些都在生产包中,确切地说根本不重要。
所以对于这个问题,我更喜欢有一个帮助文件来收集所有可选择的库并导出它们:
// helper file
export { default as Index } from './Login';
export { default as OtherComponent } from './OtherComponent';
然后当你想使用:
import { Index, OtherComponent } from 'helper';
~~~
render() {
const MyComponent = someCondition ? Index : OtherComponent;
return (
<MyComponent />;
);
}
解法:
const allPaths = {
path1: require('file path1').default,
path2: require('file path2').default
};
render(){
const MyComponent = allPaths["path1"];
return <MyComponent/>
}
我有一个 path.json 包含组件路径的文件
// path.json
{
"main": "./login/index.js",
"paths": [
{
"name": "login",
"path": "./login/index.js",
"image": ""
}
]
}
我想在 React Native 中动态加载 './login/index.js' 文件并渲染这个特定文件
我目前的实现
const MyComponent = createLazyContainer(() => {
const componentPath = PathJson.main; // ./login/index.js
return import(`${componentPath}`); //import error here @ line 7
});
export default MyComponent;
我收到以下错误:
Invalid call at line 7: import("" + componentPath)
在 React Native 中,所有导入的文件都捆绑在一起,只有那些文件可以动态导入。
假设您有三个文件 index.js
、test_1.js
和 test_2.js
,如果您只在 index.js
中导入了 test_1.js
,那么 React Native 只会捆绑这两个文件,留下 test_2.js
.
所以要回答你的问题,即使动态导入在 React Native 中有效,但因为这些文件不是包的一部分,你无法导入它们。
人们在讨论帖中告诉您的是正确的,但我想添加一个可能的解决方案。所有 imports/require 都在编译时解析,而不是在您尝试执行的 运行 时解析。当您 运行 您的应用程序时,如果您尚未导入文件,则无法使用它们。
有一个变通方法,假设您事先知道所有文件,即执行类似于工厂的操作:
const possiblePaths = {
'one': require('path/to/file/1),
'two': require('path/to/file/2)
}
funtion(type){
return possiblePaths[type]
}
然后你可以像这样使用它:
render(){
const MyComponent = function('one')
return <MyComponent/>
}
这或多或少是伪代码,我不能马上工作,但希望你明白了。您需要存储对每个可能需要的导入的引用,然后不要使用导入,使用在编译时为您创建的引用。
我曾经遇到过类似的情况,我需要通过变量进行导入,但那是 仅限于在组件内部导入组件 并且它 使用代码拆分(编辑:我正在寻找不依赖代码拆分的解决方案,我刚刚意识到问题中有一个 react-native 标签,我不认为代码-splitting 在 RN 中是一个不错的选择)。我不确定我的方法能为您提供多少帮助,但就这样吧。
旁注:
- 导入包含
index.js(jsx|ts|tsx)
文件的文件夹应自动解析为该index
文件。 - 从
from './login/index.js'
导入通常会引发 'Module not found' 错误。导入from './login/index'
或from './login
但我更喜欢最后一个,因为它最短且最简单。
在path.json
中:
{
"main": "./login", // '.js' is removed
"paths": [
{
"name": "login",
"path": "./login/index.js", // Not sure what this is for, but if necessary, remove the '.js' here as well
"image": ""
}
]
}
在MyComponent.js
:
import React, { lazy, Suspense } from 'react'
import PathJson from './path'
// 1. We need a UI to show while component is being loaded
const Loader = () => <div>{'Loading...'}</div>
// 2. We need a fallback UI if component is not found
const DocUnavailable = () => <div>{'We\'re sorry, but this document is unavailable.'}</div>
// 3. Create a resolver function ('resolver' is just a name I give)
function resolveImport(pathToComponent, FallbackComponent) {
let componentFound = false
let RenderComponent = () => <FallbackComponent /> // Assign fallback first
try {
if (require.resolve(pathToComponent)) {
componentFound = true
}
} catch (e) { } // Kinda hacky, if you don't mind, but it works
if (componentFound) {
// If found, replace fallback with the valid component
RenderComponent = lazy(() => import(pathToComponent))
}
return RenderComponent
}
// 4. Finally, implement it in a component
class MyComponent extends React.Component {
render() {
const componentPath = PathJson.main
const RenderComponent = resolveImport(componentPath, DocUnavailable)
return (
<Suspense fallback={<Loader />}>
<RenderComponent />
</Suspense>
)
}
}
export default MyComponent
参考文献:
- 'resolver' 函数的实现 based on Langutil
- 代码拆分
lazy
&Suspense
based on React Docs
实际上,React Native 开发问题不像 Web 的开发。
正因如此,在react-native项目的制作中lazy加载根本不是那么重要。只需导入您想要的任何内容,然后在项目的任何文件中使用它们。所有这些都在生产包中,确切地说根本不重要。
所以对于这个问题,我更喜欢有一个帮助文件来收集所有可选择的库并导出它们:
// helper file
export { default as Index } from './Login';
export { default as OtherComponent } from './OtherComponent';
然后当你想使用:
import { Index, OtherComponent } from 'helper';
~~~
render() {
const MyComponent = someCondition ? Index : OtherComponent;
return (
<MyComponent />;
);
}
解法:
const allPaths = {
path1: require('file path1').default,
path2: require('file path2').default
};
render(){
const MyComponent = allPaths["path1"];
return <MyComponent/>
}