通过变量动态导入文件-反应本机

时间:2020-03-06 10:46:44

标签: reactjs react-native ecmascript-6 metro-bundler

我有一个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行的无效调用:import(“” + componentPath)

5 个答案:

答案 0 :(得分:4)

人们在线程中告诉您的内容是正确的,但我想添加一种可能的解决方案。所有的导入/需求都在编译时解决,而不是在您尝试执行的运行时解决。在运行应用程序时,如果尚未导入文件,则无法使用它们。

有一个解决方法,假设您事先知道可能要执行工厂操作的所有文件:

   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/>
}

这或多或少是伪代码,我无法立即使用,但希望您能理解。您需要存储对您可能需要的每个导入的引用,然后不要使用导入,请使用在编译时为您创建的引用。

答案 1 :(得分:0)

在React Native中,所有要导入的文件都捆绑在一起,只有那些文件可以动态导入。

假设您有三个文件index.jstest_1.jstest_2.js,并且如果您仅在test_1.js中导入了index.js,那么React Native只会捆绑这些文件两个文件离开test_2.js

因此即使动态导入在React Native中可以工作也要回答您的问题,但是由于这些文件不是捆绑包的一部分,因此您无法导入它们。

答案 2 :(得分:0)

我曾经遇到过类似的情况,我需要按变量进行导入,但是仅限于在组件内部导入组件,并且它使用代码拆分 >(编辑:我一直在寻找一种不依赖于代码拆分的解决方案,我只是意识到问题中有一个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


参考文献:

答案 3 :(得分:0)

实际上, React Native 开发的问题与 Web 的开发不同。

正因为如此,在本机反应项目的生产中让懒惰加载根本不是那么重要。只需导入所需的任何内容,然后在项目的任何文件中使用它们即可。所有这些都在生产捆绑中,这一点都不重要。

因此,对于这个问题,我更喜欢有一个帮助程序文件来收集所有可选择的库并导出它们:

// 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 />;
  );
}

答案 4 :(得分:0)

解决方案:

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

  return <MyComponent/>
 }