All files / src StackUtils.js

92.86% Statements 26/28
91.3% Branches 21/23
100% Functions 10/10
100% Lines 25/25
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                3x             14x 14x 14x                                 25x     38x         3x 50x       3x 32x 32x 45x   32x 32x               3x 17x 36x 85x 36x       49x 36x   23x     13x   36x 36x      
/* @flow */
 
import React from 'react'
import { matchPath } from 'react-router'
import type { Location, MatchPathOptions } from 'react-router'
import type { Route } from './TypeDefinitions'
 
// Test if current stack item should be updated
export const shouldUpdate = (
  currentItem: MatchPathOptions,
  nextItem: MatchPathOptions,
  currentLocation: Location,
  nextLocation: Location,
): boolean => {
  // Get entries and matchs
  const matchCurrentRoute = matchPath(currentLocation.pathname, currentItem)
  const matchNextRoute = matchPath(nextLocation.pathname, nextItem)
  return (
    // Test if pathames are different
    currentLocation.pathname !== nextLocation.pathname &&
    // case 1) basic pathname
    (currentItem.path !== nextItem.path ||
      // case 2) pathname with query params
      // ex: with same path article/:id,
      //     pathname article/2 !== article/3
      (matchCurrentRoute !== null &&
        matchNextRoute !== null &&
        Object.keys(matchCurrentRoute.params).length !== 0 &&
        Object.keys(matchNextRoute.params).length !== 0 &&
        currentLocation.pathname !== nextLocation.pathname))
  )
}
 
// Get stack item from a specific route
export const get = <Item>(items: Array<Item>, route: Route): Item => ({
  ...route,
  ...items.find(item => {
    return item && item.key && route.routeName === item.key
  }),
})
 
// Generate unique key
export const createKey = (route: Route): string => {
  return `${route.key}-${Date.now()}`
}
 
// Get current route from a specific history location
export const getRoute = (stack: Array<Object>, location: Location): ?Route => {
  const { pathname } = location
  const item = stack.find(stackItem => {
    return matchPath(pathname, stackItem)
  })
  Iif (!item || !item.key) return null
  return {
    key: createKey(item),
    routeName: item.key,
    match: matchPath(pathname, item),
  }
}
 
// Build stack with React elements
export const build = <Item>(children: React$Node): Array<Item> => {
  return React.Children.toArray(children).reduce((stack, child) => {
    const item = Object.keys(child.props).reduce((props, key) => {
      if (key === 'path') {
        return {
          ...props,
          key: child.props[key],
        }
      } else if (key === 'render' || key === 'component' || key === 'children') {
        return {
          ...props,
          [key]: () => React.cloneElement(child),
        }
      }
      return props
    }, child.props)
    Iif (!item.key) return stack
    return [...stack, item]
  }, [])
}