通过变量动态导入文件- react native

6ovsh4lw  于 2023-02-05  发布在  React
关注(0)|答案(5)|浏览(214)

我有一个包含组件路径的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;

我收到以下错误:
第7行的呼叫无效:导入(""+组件路径)

jk9hmnmh

jk9hmnmh1#

人们在帖子中告诉你的是正确的,但我想添加一个可能的解决方案。所有导入/require都是在编译时解决的,而不是在运行时解决的,这是你试图做到的。在你运行应用时,如果你没有导入文件,你就不能使用它们。
有一个变通办法tho,假设你知道所有的文件,你可能提前这是做一些像工厂:

const possiblePaths = {
    'one': require('path/to/file/1'),
    'two': require('path/to/file/2')
}
    
function(type){
    return possiblePaths[type];
}

然后你用它来表达

render(){
    const MyComponent = function('one');

    return <MyComponent/>;
}

这或多或少是伪代码,我不会马上工作,但希望你得到的想法。您需要存储一个引用到每个导入您可能需要然后不使用导入,使用引用是为您创建在编译时。

x6492ojm

x6492ojm2#

实际上,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 />;
  );
}
5gfr0r5j

5gfr0r5j3#

解决方案:

const allPaths = {
  path1: require('file path1').default,
  path2: require('file path2').default
};
render(){
  const MyComponent = allPaths["path1"];

  return <MyComponent/>
 }
u4dcyp6a

u4dcyp6a4#

在React Native中,正在导入的所有文件都捆绑在一起,只有这些文件可以动态导入。
假设您有三个文件index.jstest_1.jstest_2.js,并且如果您仅将test_1.js导入index.js中,则React Native将仅绑定这两个文件,并将其导出test_2.js
因此,为了回答您的问题,即使动态导入在React Native中工作,但由于这些文件不是捆绑包的一部分,您无法导入它们。

x3naxklr

x3naxklr5#

我曾经遇到过类似的情况,我需要通过变量进行导入,但这仅限于在组件中导入组件,而且它使用代码拆分(编辑:我正在尝试寻找一个不依赖于代码拆分的解决方案,我刚刚意识到问题中有一个react-native标记,我不认为代码拆分是一个好的选择,在RN中)。我不确定我的方法能帮到你多少,但是这里。
旁注:

  • 包含index.js(jsx|ts|tsx)文件的导入文件夹应自动解析为该index文件。
  • from './login/index.js'导入通常会抛出一个 "找不到模块" 错误。导入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

参考文献:

  • "解析器"函数based on Langutil的实现
  • 基于React Docs的lazySuspense代码拆分

相关问题