grey
grey

Reputation: 23

Nested routes (/:foo/:bar) with parameters do not render, why?

So, I'm not sure if I should've structured my app different or if I'm doing something fundamentally wrong. I'm a bit confused, but let's explain first things first.

In the first navigation level, there are 4 pages - and for every page, there is a detail page.

The article category pages are exactly the same. They all hold a list (<ul><li><Link></Link></li><li>...</ul>) of 10-20 articles, so I actually just created one component, the article category component.

To make this work, the main navigation of the app holds <Link>'s which have a param called page passed to the article category component. Depending on this parameter, the view looks for the articles in an array and uses another component to render them as a list.

The article array itself holds the name of the the article and the parameter article name, f.e. this-is-an-article. I'm passing the article name parameter to the detail component which looks, depending on this and the page parameter, for the correct article.

Okay, so I hope this is clear. Now, this is my react-router configuration:

export default (
    <Route path="/" handler={App}>
        {/* Home */}
        <DefaultRoute name="home" handler={Home}/>

        {/* Page */}
        <Route name="category" path=":category" handler={Category}>
            <Route name="category.article" path=":article" handler={Article} />
        </Route>

        {/* Not found */}
        <NotFoundRoute handler={NotFound} />
    </Route>
);

.. but this doesn't work. If I click on an article link which has the correct parameters, nothing happens - well, the URL changes, but nothing else.. and the navigation menu item stays active, which is good. I at least know the parameters are correct because when I change my route confgiruation below /* Page */ to this:

    <Route name="category" path=":category" handler={Category} />
    <Route name="category.article" path=":category/:article" handler={Article} />

it works, but in my main navigation, the naivgation item isn't active anymore when I'm on an article (detail) page, I guess because it's not a child route anymore, so the configuration above this should be the correct one, but it doesn't work..

Below, there are the relevant components and their code + the content array/object. Mind you, the code shown is without any import's (I'm using ES6 with Babel through Webpack), but of course there are some.

Article component (renders the article itself)

let Article = React.createClass({
    getInitialState() {
        return {
            article: this.props.params.article,
            category: this.props.params.category
        }
    },
    componentWillReceiveProps(nextProps) {
        this.setState({
            article: nextProps.params.article,
            category: nextProps.params.category
        })
    },
    render() {
        let content = this._getContent();

        return (
            <div className="page_content page_content-article">
                <ArticleHeader />
                {content}
            </div>
        )
    },
    _getContent() {
        let item;

        for(item of ContentStore[this.state.category]) {
            if(item.name === this.state.article) {
                return item.content;
            }
        }
    }
});

Category component (renders the article list with the ArticleList component which just renders with the category and article params and is the same for each category)

let Index = React.createClass({
    getInitialState() {
        return {
            category: this.props.params.category
        };
    },
    componentWillReceiveProps(nextProps) {
        this.setState({
            category: nextProps.params.category
        });
    },
    render() {

        return (
            <div className={'page_content page_content-' + this.state.category}>
                <ArticleList articles={this._getArticles()} category={this.state.category} />
            </div>
        )
    },
    _getArticles() {
        return ContentStore[this.state.category];
    }
});

App component

let App = React.createClass({
    render() {
        return (
            <div className="page">
                <RouteHandler />
                <Navigation />
            </div>
        )
    }
});

PageStore (Example of the data - this renders the main navigation)

PageStore: [
    {
        id: 1,
        title: 'Home',
        iconClass: 'home',
        linkTo: 'home',
        params: null
    },
    {
        id: 2,
        title: 'Category 1',
        iconClass: 'foo',
        linkTo: 'category',
        params: {
            category: 'foo',
        }
    },
    ...
]

ContentStore (example of the data - this renders the article lists and the detail view as it has it's content)

ContentStore: {
    // "foo" is the category name
    foo: [
        {
            id: 1,
            name: 'article-1',
            linkText: 'Article 1',
            content: (
                <div>
                    lorem ipsum...
                </div>
            )
        },

    ]
} 

I have two questions:

I also ask if I actually should do this because well.. I never see nested routes where both, the parent and the child, have props. Maybe this is actually a bad thing to do.. I'm not sure. If you need any more information, I'm happy to provide it and thanks you in advance.

Upvotes: 2

Views: 173

Answers (1)

Hatem Jaber
Hatem Jaber

Reputation: 2402

I've never seen the use of the : before the path, I even checked the docs to see if there was an example and couldn't find one, maybe I missed it, the : is used for parameters as far as I know. Anyhow, try this:

<Route path="/" handler={App}>
    {/* Home */}
    <DefaultRoute name="home" handler={Home}/>

    {/* Page */}
    <Route path="category" handler={Category}>
        <Route path="category/article" handler={Article} />
    </Route>

    {/* Not found */}
    <NotFoundRoute handler={NotFound} />
</Route>

See if that gets the pages working for now and than go from there.

Upvotes: 0

Related Questions