Skip to content

Commit

Permalink
[changed] <Link/>s to take params property
Browse files Browse the repository at this point in the history
- old behavior is maintained, but logs a
  deprecation warning

- instead of passing in properties to fill in
  the dynamic segments, we just take it from the
  params object

closes remix-run#217
  • Loading branch information
ryanflorence committed Aug 26, 2014
1 parent 1fcf686 commit 8d2f3ed
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 32 deletions.
16 changes: 16 additions & 0 deletions UPGRADE_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ they refer to.
0.5.x -> 0.6.x
--------------

### Link params

Links should now pass their params in the `params` property, though the
old behavior will still work, you should update your code soon because
it will be removed by `v1.0`

```js
// 0.5.x
<Link to="user" userId="123"/>

// 0.6.x
<Link to="user" params={{userId: "123"}}/>
```

### Dynamic Segments, keys, and lifecycle methods

If you have dynamic segments and are depending on `getInitialState`,
`componentWillMount`, or `componentDidMount` to fire between transitions
to the same route--like `users/123` and `users/456`, then you have two
Expand Down
26 changes: 19 additions & 7 deletions docs/api/components/Link.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,28 @@ Props

The name of the route to link to, or a full URL.

### `params`

Object, the parameters to fill in the dynamic segments of your route.

#### Example

```js
// given a route config like this
<Route name="user" path="/user/:userId"/>

// create a link with this
<Link to="user" params={{userId: "123"}}/>

// though, if your user properties match up to the dynamic segements:
<Link to="user" params={user}/>
```

### `query`

Object, Query parameters to add to the link. Access query parameters in
your route handler with `this.props.query`.

### `[param]`

Any dynamic segments the route defines (like `:userId`) are passed by
name through the link's properties to the resulting url.

### `activeClassName`

The className a `Link` receives when it's route is active. Defaults to
Expand All @@ -44,7 +56,7 @@ Example
Given a route like `<Route name="user" path="/users/:userId"/>`:

```xml
<Link to="user" userId={user.id} query={{foo: bar}}>{user.name}</Link>
<Link to="user" params={{userId: user.id}} query={{foo: bar}}>{user.name}</Link>
<!-- becomes one of these depending on your router and if the route is
active -->
<a href="/users/123?foo=bar" class="active">Michael</a>
Expand All @@ -54,6 +66,6 @@ active -->
<Link to="/users/123?foo=bar">{user.name}</Link>

<!-- change the activeClassName -->
<Link activeClassName="current" to="user" userId={user.id}>{user.name}</Link>
<Link activeClassName="current" to="user" params={{userId: user.id}}>{user.name}</Link>
```

4 changes: 2 additions & 2 deletions examples/animations/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ var App = React.createClass({
return (
<div>
<ul>
<li><Link to="image" service="kitten">Kitten</Link></li>
<li><Link to="image" service="cage">Cage</Link></li>
<li><Link to="image" params={{service: "kitten"}}>Kitten</Link></li>
<li><Link to="image" params={{service: "cage"}}>Cage</Link></li>
</ul>
<Transition transitionName="example">
{this.props.activeRouteHandler()}
Expand Down
2 changes: 1 addition & 1 deletion examples/data-flow/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var App = React.createClass({

render: function() {
var links = this.state.tacos.map(function(taco) {
return <li><Link to="taco" name={taco.name}>{taco.name}</Link></li>
return <li><Link to="taco" params={taco}>{taco.name}</Link></li>
});
return (
<div className="App">
Expand Down
8 changes: 4 additions & 4 deletions examples/dynamic-segments/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ var App = React.createClass({
return (
<div>
<ul>
<li><Link to="user" userId="123">Bob</Link></li>
<li><Link to="user" userId="abc">Sally</Link></li>
<li><Link to="user" params={{userId: "123"}}>Bob</Link></li>
<li><Link to="user" params={{userId: "abc"}}>Sally</Link></li>
</ul>
{this.props.activeRouteHandler()}
</div>
Expand All @@ -26,8 +26,8 @@ var User = React.createClass({
<div className="User">
<h1>User id: {this.props.params.userId}</h1>
<ul>
<li><Link to="task" userId={this.props.params.userId} taskId="foo">foo task</Link></li>
<li><Link to="task" userId={this.props.params.userId} taskId="bar">bar task</Link></li>
<li><Link to="task" params={{userId: this.props.params.userId, taskId: "foo"}}>foo task</Link></li>
<li><Link to="task" params={{userId: this.props.params.userId, taskId: "bar"}}>bar task</Link></li>
</ul>
{this.props.activeRouteHandler()}
</div>
Expand Down
2 changes: 1 addition & 1 deletion examples/master-detail/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ var App = React.createClass({

render: function() {
var contacts = this.state.contacts.map(function(contact) {
return <li key={contact.id}><Link to="contact" id={contact.id}>{contact.first}</Link></li>
return <li key={contact.id}><Link to="contact" params={contact}>{contact.first}</Link></li>
});
return (
<div className="App">
Expand Down
6 changes: 3 additions & 3 deletions examples/query-params/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ var App = React.createClass({
return (
<div>
<ul>
<li><Link to="user" userId="123">Bob</Link></li>
<li><Link to="user" userId="123" query={{showAge: true}}>Bob With Query Params</Link></li>
<li><Link to="user" userId="abc">Sally</Link></li>
<li><Link to="user" params={{userId: "123"}}>Bob</Link></li>
<li><Link to="user" params={{userId: "123"}} query={{showAge: true}}>Bob With Query Params</Link></li>
<li><Link to="user" params={{userId: "abc"}}>Sally</Link></li>
</ul>
{this.props.activeRouteHandler()}
</div>
Expand Down
36 changes: 22 additions & 14 deletions modules/components/Link.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var withoutProperties = require('../helpers/withoutProperties');
var transitionTo = require('../helpers/transitionTo');
var hasOwnProperty = require('../helpers/hasOwnProperty');
var makeHref = require('../helpers/makeHref');
var warning = require('react/lib/warning');

function isLeftClickEvent(event) {
return event.button === 0;
Expand All @@ -14,7 +15,7 @@ function isModifiedEvent(event) {
}

/**
* A map of <Link> component props that are reserved for use by the
* DEPRECATED: A map of <Link> component props that are reserved for use by the
* router and/or React. All other props are used as params that are
* interpolated into the link's path.
*/
Expand All @@ -38,12 +39,12 @@ var RESERVED_PROPS = {
*
* You could use the following component to link to that route:
*
* <Link to="showPost" postId="123"/>
* <Link to="showPost" params={{postId: "123"}} />
*
* In addition to params, links may pass along query string parameters
* using the `query` prop.
*
* <Link to="showPost" postId="123" query={{show:true}}/>
* <Link to="showPost" params={{postId: "123"}} query={{show:true}}/>
*/
var Link = React.createClass({

Expand All @@ -53,15 +54,29 @@ var Link = React.createClass({

statics: {

// TODO: Deprecate passing props as params in v1.0
getUnreservedProps: function (props) {
warning(
false,
'Passing props for params on <Link>s is deprecated, '+
'please use the `params` property.'
);
return withoutProperties(props, RESERVED_PROPS);
},

/**
* Returns a hash of URL parameters to use in this <Link>'s path.
*/
getParams: function (props) {
return props.params || Link.getUnreservedProps(props);
}

},

propTypes: {
to: React.PropTypes.string.isRequired,
activeClassName: React.PropTypes.string.isRequired,
params: React.PropTypes.object,
query: React.PropTypes.object,
onClick: React.PropTypes.func
},
Expand All @@ -78,18 +93,11 @@ var Link = React.createClass({
};
},

/**
* Returns a hash of URL parameters to use in this <Link>'s path.
*/
getParams: function () {
return Link.getUnreservedProps(this.props);
},

/**
* Returns the value of the "href" attribute to use on the DOM element.
*/
getHref: function () {
return makeHref(this.props.to, this.getParams(), this.props.query);
return makeHref(this.props.to, Link.getParams(this.props), this.props.query);
},

/**
Expand All @@ -106,7 +114,7 @@ var Link = React.createClass({
},

componentWillReceiveProps: function (nextProps) {
var params = Link.getUnreservedProps(nextProps);
var params = Link.getParams(nextProps);

this.setState({
isActive: Link.isActive(nextProps.to, params, nextProps.query)
Expand All @@ -115,7 +123,7 @@ var Link = React.createClass({

updateActiveState: function () {
this.setState({
isActive: Link.isActive(this.props.to, this.getParams(), this.props.query)
isActive: Link.isActive(this.props.to, Link.getParams(this.props), this.props.query)
});
},

Expand All @@ -135,7 +143,7 @@ var Link = React.createClass({
event.preventDefault();

if (allowTransition)
transitionTo(this.props.to, this.getParams(), this.props.query);
transitionTo(this.props.to, Link.getParams(this.props), this.props.query);
},

render: function () {
Expand Down

0 comments on commit 8d2f3ed

Please sign in to comment.