动态 React-Router 1.0.0-rc3

Dynamic React-Router 1.0.0-rc3

Regardless of what I have read from the folks at react-router, I prefer my app's router have dynamic data, and I have been successful in doing it, with one caveat: I cannot loop recursively for child routes.

这是一个工作的动态反应路由器:

export default class Index extends React.Component {

  constructor() {
    super();
    this.state = {
      navItems: [] };
  }

  componentWillMount() {
    NavMenuAPI.getAll()
      .then((response) => {
        const data = response.data;
        this.setState({ navItems: data });
      });
  }

  fetchMenuSystem(data) {
    const routes = [];
    data.map(function(route) {
      let routePaths = [];
      let component = {};
      if (route.linkTo === '/') {
        const pageApp = route.title.replace(/ /g, '-').toLocaleLowerCase();
        component = require('./components/pages/' + pageApp);
      } else {
        const pageApp = route.title.replace(/ /g, '-').toLocaleLowerCase();
        component = require('./components/pages/' + pageApp);
      }
      if (route.paths === undefined) {
        routePaths.push(route.linkTo);
      } else {
        routePaths = JSON.parse(JSON.stringify(route.paths));
      }

      routePaths.map(function(path) {
        const props = { key: path, path, component };
        // Static `onEnter` is defined on
        // component, we should pass it to route props
        // if (component.onEnter) props.onEnter = component.onEnter;
        routes.push(<Route { ...props } />);
      });

      //////////////////////////////////////////////
      //  PROBLEM !!!!!!!!!! 
      // if (route.childNodes !== undefined) {
      //  this.fetchMenuSystem(route.childNodes);
      // }
    });
    return routes;
  }

  fetchRoutes() {
    const data = this.state.navItems;
    const result = this.fetchMenuSystem(data);
    return (
      <Route component={ require('./components/APP') }>
        { result }
        <Route path="*" component={ require('./components/pages/not-found') }/>
      </Route>
    );
  }

  render() {
    if (this.state.navItems.length === 0) return <div>Loading ...</div>;
    const routerProps = {
      routes: this.fetchRoutes(),
      history: createHistory({
        queryKey: false
      }),
      createElement: (component, props) => {
        return React.createElement(component, { ...props });
      }
    };
    return (
      <Router { ...routerProps } />
    );
  }
}

  ReactDOM.render(<Index />, document.getElementById('reactRoot'));

正如我所说,这只适用于第一级,当我尝试递归循环任何子节点时,我收到错误:

TypeError: Cannot read property 'fetchMenuSystem' of undefined

我尝试将调用绑定到获取函数并绑定映射,none 有效。

非常感谢对此的帮助。

好的,我解决了这个问题。问题在于路由状态和 'this' 关键字。

更改如下:

export default class Index extends React.Component {

  constructor() {
    super();
    this.state = {
      navItems: [],
      routes: []
    };
  }

      ................

  fetchMenuSystem(data) {
    const currRoutesState = this.state.routes;
    const self = this;
    data.map(function(route) {

      ................

      routePaths.map(function(path) {
      ................
        currRoutesState.push(<Route { ...props } />);
      });

      if (route.childNodes !== undefined) {
        self.fetchMenuSystem(route.childNodes);
      }
    });
    return currRoutesState;
  }

      ................    

}


Final thoughts if you plan on using this:

[Re: npm install --save history]

I had to opt for 100% client side routing, (not isomorphic/universal) so in my imports ....

  import createHistory from 'history/lib/createHashHistory'; 
  //  import createBrowserHistory from 'history/lib/createBrowserHistory';