all files / modules/ Redirect.js

97.33% Statements 73/75
92.86% Branches 39/42
100% Functions 12/12
92.31% Lines 24/26
7 statements, 3 functions, 15 branches Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86                                                                                                                             
import invariant from 'invariant'
import React, { Component } from 'react'
import { createRouteFromReactElement } from './RouteUtils'
import { formatPattern } from './PatternUtils'
import { falsy } from './PropTypes'
 
const { string, object } = React.PropTypes
 
/**
 * A <Redirect> is used to declare another URL path a client should
 * be sent to when they request a given URL.
 *
 * Redirects are placed alongside routes in the route configuration
 * and are traversed in the same manner.
 */
class Redirect extends Component {
 
  static createRouteFromReactElement(element) {
    const route = createRouteFromReactElement(element)
 
    if (route.from)
      route.path = route.from
 
    route.onEnter = function (nextState, replaceState) {
      const { location, params } = nextState
 
      let pathname
      if (route.to.charAt(0) === '/') {
        pathname = formatPattern(route.to, params)
      } else Iif (!route.to) {
        pathname = location.pathname
      } else {
        let routeIndex = nextState.routes.indexOf(route)
        let parentPattern = Redirect.getRoutePattern(nextState.routes, routeIndex - 1)
        let pattern = parentPattern.replace(/\/*$/, '/') + route.to
        pathname = formatPattern(pattern, params)
      }
 
      replaceState(
        route.state || location.state,
        pathname,
        route.query || location.query
      )
    }
 
    return route
  }
 
  static getRoutePattern(routes, routeIndex) {
    let parentPattern = ''
 
    for (let i = routeIndex; i >= 0; i--) {
      let route = routes[i]
      let pattern = route.path || ''
      parentPattern = pattern.replace(/\/*$/, '/') + parentPattern
 
      Iif (pattern.indexOf('/') === 0)
        break
    }
 
    return '/' + parentPattern
  }
 
  static propTypes = {
    path: string,
    from: string, // Alias for path
    to: string.isRequired,
    query: object,
    state: object,
    onEnter: falsy,
    children: falsy
  }
 
  /* istanbul ignore next: sanity check */
  render() {
    invariant(
      false,
      '<Redirect> elements are for router configuration only and should not be rendered'
    )
  }
 
}
 
export default Redirect