react-router
Version:
A complete routing library for React.js
152 lines (118 loc) • 3.2 kB
JavaScript
import React from 'react';
import invariant from 'invariant';
import { stripLeadingSlashes, stringifyQuery } from './URLUtils';
var { func, object } = React.PropTypes;
function pathnameIsActive(pathname, activePathname) {
if (stripLeadingSlashes(activePathname).indexOf(stripLeadingSlashes(pathname)) === 0)
return true; // This quick comparison satisfies most use cases.
// TODO: Implement a more stringent comparison that checks
// to see if the pathname matches any routes (and params)
// in the currently active branch.
return false;
}
function queryIsActive(query, activeQuery) {
if (activeQuery == null)
return query == null;
if (query == null)
return true;
for (var p in query)
if (query.hasOwnProperty(p) && String(query[p]) !== String(activeQuery[p]))
return false;
return true;
}
var RouterContextMixin = {
propTypes: {
stringifyQuery: func.isRequired
},
getDefaultProps() {
return {
stringifyQuery
};
},
childContextTypes: {
router: object.isRequired
},
getChildContext() {
return {
router: this
};
},
/**
* Returns a full URL path from the given pathname and query.
*/
makePath(pathname, query) {
if (query) {
if (typeof query !== 'string')
query = this.props.stringifyQuery(query);
if (query !== '')
return pathname + '?' + query;
}
return pathname;
},
/**
* Returns a string that may safely be used to link to the given
* pathname and query.
*/
makeHref(pathname, query) {
return this.makePath(pathname, query);
},
/**
* Pushes a new Location onto the history stack.
*/
transitionTo(pathname, query, state=null) {
var { history } = this.props;
invariant(
history,
'Router#transitionTo is client-side only (needs history)'
);
history.pushState(state, this.makePath(pathname, query));
},
/**
* Replaces the current Location on the history stack.
*/
replaceWith(pathname, query, state=null) {
var { history } = this.props;
invariant(
history,
'Router#replaceWith is client-side only (needs history)'
);
history.replaceState(state, this.makePath(pathname, query));
},
/**
* Navigates forward/backward n entries in the history stack.
*/
go(n) {
var { history } = this.props;
invariant(
history,
'Router#go is client-side only (needs history)'
);
history.go(n);
},
/**
* Navigates back one entry in the history stack. This is identical to
* the user clicking the browser's back button.
*/
goBack() {
this.go(-1);
},
/**
* Navigates forward one entry in the history stack. This is identical to
* the user clicking the browser's forward button.
*/
goForward() {
this.go(1);
},
/**
* Returns true if a <Link> to the given pathname/query combination is
* currently active.
*/
isActive(pathname, query) {
var { location } = this.state;
if (location == null)
return false;
return pathnameIsActive(pathname, location.pathname) &&
queryIsActive(query, location.query);
}
};
export default RouterContextMixin;