当前位置: 首页 > 知识库问答 >
问题:

在React路由器路由中动态注入数据

刘承运
2023-03-14

我一直在尝试模块化我的React.js应用程序(它将作为带有Electron的桌面应用程序提供),如果我将来制作一个新模块,我只需添加一个新文件夹和修改几个文件,它就可以很好地集成。我最初受到这篇文章的启发:https://www.nylas.com/blog/react-plugins/

在那之后,我开始尽可能多地研究,并最终创建了一个JSON文件,该文件将保存在服务器中,其中包含为特定客户机注册的插件清单。大概是这样的:

{
    "plugins": [
        {
            "name": "Test Plugin",
            "version": "0.0.1",
            "path": "testplugin",
            "file": "test",
            "component":"TestPlugin"
        },
        {
            "name": "Another Plugin",
            "version": "0.0.1",
            "path": "anothertest",
            "file": "othertest",
            "component":"TestPluginDeux"
        }
    ]
}

之后,我制作了几个文件夹,它们匹配path值,并且包含一个与清单中的名称匹配的组件(例如,将TestPlugin组件导出为默认)。我还制作了一个pluginStore文件,该文件读取清单并在this.state中挂载插件。

然后,在谷歌和这里做了大量的研究,发现了这个答案:反应-动态导入组件

有了这个函数,我可以通过运行mountPlugins()函数在pluginStore中创建的mountPlugins()函数,在我的主页的componentDidMount()方法中遍历清单,找到目录中的文件夹,并在this.state中装载插件。

到现在为止,一直都还不错。我使用的是React路由器,我能够在该状态下动态挂载插件,并能够通过如下方式调用它们,将它们加载到我的主路由中:

我现在遇到的问题是,我想通过使用componentrender方法,动态创建从状态加载这些组件的路由,但我运气不好。我总是会得到同样的结果。。。显然,我传递的是一个对象而不是字符串。

这是我这次尝试的最后一次迭代:

{this.state.modules.registered.map((item) =>
<Route exact path={`/${item.path}`} render={function() {
  return <item.component />
  }}></Route>
)}

在那之后,我做了一个路由,它调用一个PluginShell组件,该组件由一个Navlink调用,该组件发送插件的名称来动态注入和加载它。

<Route exact path='/ex/:component' component={PluginShell}></Route>

但我最终还是遇到了同样的问题。我正在传递一个对象,而createElement函数需要一个字符串

我搜索了整个StackOverflow,发现了许多类似的问题和答案。我尝试应用所有可能的解决方案,但没有成功。

编辑:我已经整理了一个GitHub回购,它有最少的文件集来重现这个问题。

以下是链接:https://codesandbox.io/embed/aged-moon-nrrjc


共有3个答案

方博学
2023-03-14

我认为问题在于您试图呈现

尝试:

<Route exact path={`/${item.path}`} render={function() {
  return React.createElement(item.component, props)
  }}></Route>
)}

燕飞文
2023-03-14

你有正确的想法,如果有的话,我想你的语法有点不对劲。我不需要从你的例子中调整太多来获得动态路由工作。

下面是一个我认为您想要做的工作示例:

const modules = [{
  path: '/',
  name: 'Home',
  component: Hello
},{
  path: '/yo',
  name: 'Yo',
  component: Yo
}];


function DynamicRoutes() {
    return (
        <BrowserRouter>
            { modules.map(item => <Route exact path={item.path} component={item.component}/>) }
        </BrowserRouter>
    );
}

https://stackblitz.com/edit/react-zrdmcq

窦弘义
2023-03-14

好的pokey这里有很多运动部件可以大大简化。

  1. 我建议转向对开发人员更友好、更固执己见的状态存储(如Redux)。我个人从未使用过Flux,因此我只能推荐我有经验的产品。因此,可以避免使用普通类进行状态管理。

工作示例(对于这个简单的示例,我只是使用React state,我也没有接触任何其他文件,这些文件也可以简化):

App.js

import React from "react";
import Navigation from "./components/MainNavigation";
import Routes from "./routes";
import { plugins } from "./modules/manifest.json";
import "./assets/css/App.css";

class App extends React.Component {
  state = {
    importedModules: []
  };

  componentDidMount = () => {
    this.importPlugins();
  };

  importPlugins = () => {
    if (plugins) {
      try {
        const importedModules = [];
        const importPromises = plugins.map(plugin =>
          import(`./modules/${plugin.path}/${plugin.file}`).then(module => {
            importedModules.push({ ...plugin, Component: module.default });
          })
        );

        Promise.all(importPromises).then(() =>
          this.setState(prevState => ({
            ...prevState,
            importedModules
          }))
        );
      } catch (err) {
        console.error(err.toString());
      }
    }
  };

  render = () => (
    <div className="App">
      <Navigation />
      <Routes {...this.state} />
    </div>
  );
}

export default App;

路线/index.js

import React from "react";
import React from "react";
import isEmpty from "lodash/isEmpty";
import { Switch, Route } from "react-router-dom";
import ProjectForm from "../modules/core/forms/new-project-form";
import NewPostForm from "../modules/core/forms/new-post-form";
import ProjectLoop from "../modules/core/loops/project-loop";
import Home from "../home";

const Routes = ({ importedModules }) => (
  <Switch>
    <Route exact path="/" component={Home} />
    <Route exact path="/projectlist/:filter" component={ProjectLoop} />
    <Route exact path="/newproject/:type/:id" component={ProjectForm} />
    <Route exact path="/newpost/:type" component={NewPostForm} />
    {!isEmpty(importedModules) &&
      importedModules.map(({ path, Component }) => (
        <Route key={path} exact path={`/${path}`} component={Component} />
      ))}
  </Switch>
);

export default Routes;
 类似资料:
  • 问题内容: 我有以下路由配置: GuaranteeLoggedInContainer为: 但是,历史的推动力:没有用。这里没有历史。 如果我使用这样的配置: 我遇到类似的问题: reactjs中最好的身份验证方法是什么? 问题答案: 从我对您的React Router设计的了解中,您似乎正在使用React Router版本4 在这种情况下,您可以在组件本身中指定路由,并利用withRouter进行

  • 使用redux和反应路由器,我想访问路由指定的组件以外的组件上的路由参数。 我已经对react-router、redux和react-router-redux进行了如下设置,我想从我的redux存储访问reportId参数。 我已经尝试连接react-redux路由器来存储路由状态,但是我发现除了活动路由的完整路径之外,redux内部没有任何有用的存储。这让我可以选择从redux中的路径解析出re

  • 我正在使用React制作一个动态网页。我正在使用React Routers中的一个交换机组件,根据用户的需要,将主页更改为其他各种页面。我希望通过以下路由创建新帐户: 主页 我的问题在于从第三个创建帐户页面返回主页或登录页面。我可以创建链接,使我从第1页 最初,我在createaccount页面中有一个switch语句,呈现三个独立的组件。如果我在这个switch语句中设置了route home,

  • 如果我将路由折叠起来,这样看起来就像: 工作很好。我嵌套的原因是因为我将在“dashboard”下有多个子项,并且希望它们都在URL中以为前缀。

  • 我使用的反应路由器dom版本5.0.1一个简单的反应应用程序,我使用了汇总捆绑,这是我的路由器组件 问题是,它只在localhost:8000/处显示主路由,但当我尝试访问localhost:8000/hello或localhost:8000/登录时,会出现此错误 这是我的rollup.config };

  • react&React-Router的新功能。我正在使用react-router-4 我有以下组件-login-home-header-sidebar-content 登录组件没有标题或侧栏。 这就是我的路由 应用程序JS 然后在我的Home组件中,我有侧边栏和内容。 home.js呈现方法 侧边栏组件有一个链接,该链接具有“to”值“/home/dashboard”。 不幸的是,这并不奏效。单击