React-router: 1.0.0-beta3: Need ability to add a React key to a route's component for animation

Created on 11 Aug 2015  路  4Comments  路  Source: ReactTraining/react-router

As far as I can tell there is no way to get the router to add a unique key to the components that are rendered for a given route. This makes it impossible to use CSSTransitionGroup to wrap {this.props.children} to achieve animations between routes since the child component has no key and can't be distinguished from any other component by the transition group. Am I missing something. I've read the source and found no way to do this.

Happy to submit a PR to allow for the setting of a key, but want to make sure I'm not missing something first.

Most helpful comment

Found a way to do this by the way. You can specify a custom createElement function and pass it to the Router like so:

const createElement = (Component, props) => {
  return <Component key={`${props.route.name}RouteComponent`} {...props}/>
}

<Router children={routes} createElement={createElement} />

All 4 comments

Found a way to do this by the way. You can specify a custom createElement function and pass it to the Router like so:

const createElement = (Component, props) => {
  return <Component key={`${props.route.name}RouteComponent`} {...props}/>
}

<Router children={routes} createElement={createElement} />

or in your normal render method <div>{React.cloneElement(this.props.children, { key: 'some key' })}</div>

@mhodgson here's a big THANK YOU! I only had to change props.route.name to props.route.path since .name was undefined in my case so all the keys were the same - that's it. So now i can do this:

<ReactTransitionGroup ...>{this.props.children}</ReactTransitionGroup>

which is AWESOME! instead of this:

<ReactTransitionGroup ...>
    {React.cloneElement(this.props.children, { key: 'some key' })}
</ReactTransitionGroup>

I used to do the latter, like @ryanflorence said, and it works perfectly, but ONLY for 1-level deep route hierarchies (i.e. no nesting!). Once you have wrapper1 > wrapper2 > content, any navigation between child content components would redraw wrapper2 because of cloneElement, but no more!

YAY!

I found that adding a createElement Component obfuscated my intentions.

Instead, you can combine map and cloneElement right at the point of interest:

{ // Key children based on their route name
  React.Children.map(children, (child) => {
    return React.cloneElement(child, { key: child.props.route.path });
  })
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

winkler1 picture winkler1  路  3Comments

ArthurRougier picture ArthurRougier  路  3Comments

ryansobol picture ryansobol  路  3Comments

imWildCat picture imWildCat  路  3Comments

davetgreen picture davetgreen  路  3Comments