从JSON动态定义ReactJS路由

时间:2016-08-11 17:32:01

标签: javascript json reactjs ecmascript-6 react-router

我有一个全局JSON配置,它具有各种配置数据,包括路由名称和我希望为路由呈现的组件。我想从这个JSON配置动态构建我的路由。我现在能够动态生成路由,但是,由于路径组件是JSON文件中的字符串,React不喜欢它们并抛出下面的错误。有关实现这一目标的任何建议吗?

warning.js:44 Warning: Unknown props `history`, `location`, `params`, `route`, `routeParams`, `routes` on <Dashboard> tag. Remove these props from the element. For details, see https://f b.me/react-unknown-prop
    in Dashboard
    in RouterContext
    in Router

相关的JSON代码段:

{
    "routes" : [
        {
            "route_name"              : "home",
            "path"                   : "/",
            "visible_in_menu"         : true,
            "menu_title"              : "Home",
            "menu_font_awesome_icon"  : "fa fa-home",
            "component"              : "App",
            "child_routes"            : null
        },
        {
            "route_name"              : "analytics",
            "path"                   : "/analytics",
            "visible_in_menu"         : true,
            "menu_title"              : "Analytics",
            "menu_font_awesome_icon"  : "fa fa-bar-chart",
            "component"              : "Dashboard",
            "template"                : null,
            "child_routes" : [
                {
                    "route_name"      : "analytics_daily" ,
                    "path"           : "/daily",
                    "visible_in_menu" : true,
                    "menu_title"      : "Daily",
                    "component"      : "Dashboard"
                }
            ]
        }
    ]
}

获取配置并动态构建路由的代码:

import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, Link, browserHistory } from 'react-router'
import $ from 'jquery';

import App from './App'; 
import Dashboard from './Dashboard';
import SidebarMenu from './SidebarMenu';

import './index.css';

$.get("/routes_menu_config.json", bootstrapApplication);

function bootstrapApplication(config){

    var dynamicRoutesJSX = buildDynamicRoutes(config);

    // Add dynamic routes to app
    ReactDOM.render((
      <Router history={browserHistory}>
        {dynamicRoutesJSX}
      </Router>
    ), document.getElementById('root'));

    // Render sidebar menu
    ReactDOM.render(
        <SidebarMenu />,
        document.getElementById('menu')
    ); 

}

function buildDynamicRoutes(config){

    var routeJSX = [];

    for (let [index, route] of config.routes.entries()) {
      routeJSX.push(<Route path={route.path} components={route.component} key={index}/>);       
    }

    return routeJSX;
}

我还尝试了普通对象实例化路由而不是使用JSX,但它产生了同样的错误:

$.get("/routes_menu_config.json", bootstrapApplication);

function bootstrapApplication(config){

    var dynamicRoutesJSX = buildDynamicRoutes(config);

    // Add dynamic routes to app
    ReactDOM.render(<Router history={browserHistory} routes={dynamicRoutesJSX} 

    // Render sidebar menu
    ReactDOM.render(
        <SidebarMenu />,
        document.getElementById('menu')
    ); 

}


function buildDynamicRoutes(config){

    var routes = [];

    // Iterate parent routes from config
    for (var i=0; i<config.routes.length; i++) {

        var configParentRouteDefinition = config.routes[i];

        // Create parent route definition
        var parentRouteDefinition = {
            path : configParentRouteDefinition.path,
            component: configParentRouteDefinition.component
        };

        // If there are child routes, add them to the definition
        if(configParentRouteDefinition.child_routes){

            // Track child routes
            var childRoutes = [];

            // Iterate child routes, generate definition
            for(var j=0; j<configParentRouteDefinition.child_routes.length; j++){

                var configChildRouteDefinition = configParentRouteDefinition.child_routes[j]


                var childRouteDefinition = {
                    path : configChildRouteDefinition.path,
                    component: configChildRouteDefinition.component         
                };

                childRoutes.push(childRouteDefinition);
            }

            // Ad the definition to the parent route definition
            parentRouteDefinition["childRoutes"] = childRoutes;

        }

        routes.push(parentRouteDefinition);

    }

    return routes;

}

3 个答案:

答案 0 :(得分:4)

您需要创建组件注册表,以便从名称中查找组件引用:

import App from './App'; 
import Dashboard from './Dashboard';

const componentRegistry = {
    "App": App,
    "Dashboard": Dashboard
}

<Route path={route.path} components={componentRegistry[route.component]} key={index}/>;

答案 1 :(得分:1)

如果您使用例如Webpack可以在不导入所有组件的情况下获得您想要的结果。但是,您必须将路径传递给组件而不是组件的名称。像这样:

json file:
{"nav": [
{
  "label": "HOME",
  "route": {
    "url": "/",
    "exact": true
  },
  "component": {
    "path": "home",
    "name": "home"
  }
}}
createRoutes() {
    return this.props.data.nav.map((item: any, index: number) => {
        let DynamicComponent = require('../../' + item.component.path + '/' + item.component.name).default;
        return <Route key={index} path={item.route.url}
                      exact={item.route.exact}
                      render={() => (<DynamicComponent key={item.component.name}/>)}/>
    });
}

答案 2 :(得分:-1)

这个为我工作

App.tsx

import routes from "./routes";
const App: React.FC = () => {
  return (
      <BrowserRouter>
        <div>
          <Switch>
            {routes.data.map((entry) => {return (<Route {...entry}/>)})}
          </Switch>
        </div>
      </BrowserRouter>
  );
};

export default App;

router.ts

const routes = {data: [
        {
            key: "one",
            path: "/three"

        },
        {
            key: "two",
            path: "/two"
        }
    ]
}

export default routes;