2016-08-11 105 views
3

我有一個全局JSON配置,它具有各種配置數據,包括路由名稱和我想爲路由呈現的組件。我想從這個JSON配置動態構建我的路線。我目前能夠動態生成路由,但是,由於路由組件是JSON文件中的字符串,因此React不喜歡它們並引發下面的錯誤。任何有關完成此目標的建議?從JSON動態定義ReactJS路由

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

您需要創建組件的註冊表,使你可以從他們的名字查找組件引用:

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

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

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

This Works,thanks。我希望有一種方法可以將字符串轉換爲實例化的組件。 – ph34r

+0

不幸的是,一個字符串告訴React渲染一個HTML節點,它不會內部跟蹤哪些組件存在,因此無法查找它們。 – Aaron

+0

這對我有用,謝謝。 – rorymorris89

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