使用 React.lazy 动态地 select 一个组件
Using React.lazy to dynamically select a component
我正在开发一个显示任务列表的应用程序。当用户单击任务时,它应该显示一个表单,以便用户可以更新该任务的状态。然而,有不同类型的任务,需要根据任务类型呈现正确的形式。每个任务类型都有一个任务定义,其中包含一个标识该任务所需表单的字段。当有人点击一个任务时,任务对象,包括任务 formComponent 被传递给 formWrapper 组件。每个表单组件都在一个 JSX 文件中,它们都导出为 TaskForm。
我需要 select 基于任务定义的组件。我认为我可以通过执行以下操作 react.Lazy 来完成此操作:
在formWrapper的componentDidMount():
// Store the path to the required JSX file in the state.
this.setState( {formFile: '../Processes/'+this.state.task.formComponent} );
然后在formWrapper的render()中:
TaskForm = React.lazy(() => import(this.state.formFile));
return (
<Suspense fallback={<div>Loading...</div>}>
<TaskForm task={this.props.task} />
</Suspense>
当我启动 node.js 时,它会抛出警告“关键依赖项:依赖项的请求是一个表达式”并且无法加载表单。
我离正确的轨道还很近吗?我不能静态定义表单。其中有几个,它们可能会发生变化。
代码必须是静态可分析的,因为 Webpack(我相信这是您用来捆绑应用程序的工具)需要知道需要哪些文件,以便将它们包含在捆绑包中。采用 this.state.formFile
.
这样的表达式是不够聪明的
我相信当您说您不能静态定义表单时是不正确的,或者至少不能容忍这样做。文件是可枚举的,都可以导入到这个文件中。
我想您想根据某些条件动态导入组件。我为此创建了一个小函数:
const getComponent = (path) => {
const Component = React.lazy(() => import(`${path}`));
return Component;
};
// Usage
render() {
const Component = getComponent(path);
return <Component />;
}
这是工作沙盒:https://codesandbox.io/s/intelligent-snowflake-c0l6y?file=/src/App.js:306-344
这是实时部署的应用程序:https://csb-c0l6y.netlify.app/
您可以通过网络请求确认,当我们Load Component B
请求新文件时。
Note:
我还没有对这个模式进行实战测试。我认为它可能对性能有一些影响,但应该很容易修复。
在与@backtick 交流后,我最终的解决方案是将所有表单 JSX 文件放在一个文件夹中,其中包含一个 index.js 文件,该文件导出文件夹中的每个表单(没有其他代码在文件中,仅导出):
export { Form1 } from './Form1';
export { Form2 } from './Form2';
然后,在需要加载其中一个表单的文档中,我从数据库中读取表单名称,并使用它在我的 render() 函数中延迟加载表单:
const MyForm = React.lazy(() => import('../forms')
.then(forms => (
{ default: forms[this.state.formFile] }
))
);
.then函数默认导出选中的表单,MyForm中只保存一个组件。如果 this.state.formFile = Form1,则加载 Form1。
在我的表单的 return() 中,我将 MyForm 作为一个组件包含在内:
<Suspense fallback={<div>Loading...</div>}>
<MyForm task={this.props.task} formVariables={this.state.formVariables}/>
</Suspense>
我正在开发一个显示任务列表的应用程序。当用户单击任务时,它应该显示一个表单,以便用户可以更新该任务的状态。然而,有不同类型的任务,需要根据任务类型呈现正确的形式。每个任务类型都有一个任务定义,其中包含一个标识该任务所需表单的字段。当有人点击一个任务时,任务对象,包括任务 formComponent 被传递给 formWrapper 组件。每个表单组件都在一个 JSX 文件中,它们都导出为 TaskForm。
我需要 select 基于任务定义的组件。我认为我可以通过执行以下操作 react.Lazy 来完成此操作:
在formWrapper的componentDidMount():
// Store the path to the required JSX file in the state.
this.setState( {formFile: '../Processes/'+this.state.task.formComponent} );
然后在formWrapper的render()中:
TaskForm = React.lazy(() => import(this.state.formFile));
return (
<Suspense fallback={<div>Loading...</div>}>
<TaskForm task={this.props.task} />
</Suspense>
当我启动 node.js 时,它会抛出警告“关键依赖项:依赖项的请求是一个表达式”并且无法加载表单。
我离正确的轨道还很近吗?我不能静态定义表单。其中有几个,它们可能会发生变化。
代码必须是静态可分析的,因为 Webpack(我相信这是您用来捆绑应用程序的工具)需要知道需要哪些文件,以便将它们包含在捆绑包中。采用 this.state.formFile
.
我相信当您说您不能静态定义表单时是不正确的,或者至少不能容忍这样做。文件是可枚举的,都可以导入到这个文件中。
我想您想根据某些条件动态导入组件。我为此创建了一个小函数:
const getComponent = (path) => {
const Component = React.lazy(() => import(`${path}`));
return Component;
};
// Usage
render() {
const Component = getComponent(path);
return <Component />;
}
这是工作沙盒:https://codesandbox.io/s/intelligent-snowflake-c0l6y?file=/src/App.js:306-344
这是实时部署的应用程序:https://csb-c0l6y.netlify.app/
您可以通过网络请求确认,当我们Load Component B
请求新文件时。
Note:
我还没有对这个模式进行实战测试。我认为它可能对性能有一些影响,但应该很容易修复。
在与@backtick 交流后,我最终的解决方案是将所有表单 JSX 文件放在一个文件夹中,其中包含一个 index.js 文件,该文件导出文件夹中的每个表单(没有其他代码在文件中,仅导出):
export { Form1 } from './Form1';
export { Form2 } from './Form2';
然后,在需要加载其中一个表单的文档中,我从数据库中读取表单名称,并使用它在我的 render() 函数中延迟加载表单:
const MyForm = React.lazy(() => import('../forms')
.then(forms => (
{ default: forms[this.state.formFile] }
))
);
.then函数默认导出选中的表单,MyForm中只保存一个组件。如果 this.state.formFile = Form1,则加载 Form1。
在我的表单的 return() 中,我将 MyForm 作为一个组件包含在内:
<Suspense fallback={<div>Loading...</div>}>
<MyForm task={this.props.task} formVariables={this.state.formVariables}/>
</Suspense>