Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/router / src / OneRouterProvider.tsx
Size: Mime:
/**
 * @todo @@perf @deprecated need to update to not use old context
 * @type @see https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-router/index.d.ts
 * @see https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/RouterContext.js
 */
import * as React from 'react'
import { isFunction } from 'exotic'
/**
 * @todo typings for export without making it a type (also this has outdated types)
 */
import { __RouterContext as RouterContext } from 'react-router'
import { ComponentType } from 'react'
import {
  OneRouterToRuleThemAll as OneRouter,
  EMPTY_ROUTER,
} from './OneRouterToRuleThemAll'
import { oneRouter } from './oneRouter'
import { ReactRouterContextType, ReactRouterContextValue } from './typings'
import { OneRouterContext } from './Context'

/**
 * @name OneRouterProvider < adding as alias instead of `container`
 *
 * @todo @@perf PureComponents
 *
 * @todo we also want to provide context
 *  (since `react-router` does not export theirs publicly yet)
 *  this will require changing it from
 * @example
 *    <>
 *      <OneRouterContainer />
 *      <App />
 *    </>
 *
 * =>
 *    <>
 *      <OneRouterContainer>
 *        <App />
 *      <OneRouterContainer />
 *    </>
 */
class OneRouterWrap extends React.Component {
  /**
   * @note this is the same as <RouterContext.Consume>
   */
  static contextType = RouterContext as ReactRouterContextType<OneRouter>
  context: ReactRouterContextValue<OneRouter>

  componentWillMount() {
    const props = this.props
    oneRouter.props = props

    /**
     * @todo update oneRouter.router type
     *       - if `Route` is not available
     *       - or update our typings
     *
     * ensure it is not the default empty
     */
    if (this.context !== (EMPTY_ROUTER as any)) {
      // not triggering...
      // const error = new Error(JSON.stringify(this.context, undefined, 2))
      // console.error(error)

      oneRouter.router = this.context

      // frozen by react always actually...
      if (Object.isExtensible(this.context) === true) {
        this.context.oneRouter = oneRouter
      }
    } else {
      console.warn('[@skava/router] context was empty!')
    }
  }

  // !!!!! @todo when finished, delete this !!!!!!
  // componentWillMount() {
  //   const props = this.props
  //   // console.log('PROPS_WILLMOUNT__', JSON.stringify(props, null, 2))
  //   oneRouter.props = props
  //   oneRouter.router = this.context.router || props.router
  //   // oneRouter.history = oneRouter.history.router || oneRouter.history
  //   // const { history, isSSR } = this.props
  //   // if (!isSSR) this.unsubscribeFromHistory = history.listen(this.handleLocationChange)
  //   // this.handleLocationChange(history.location)
  // }
  // should not be needed anymore...
  // import { object } from 'prop-types'
  // old context...
  // static contextTypes = {
  //   router: object,
  // }
  // can trigger oneRouter here too
  // @michael @bhargavi
  // // @todo !!!
  // oneRouter.onChange(change => {
  //   // import {sessionContainer} from 'state/container'
  //   // const { isRegisteredUser, isGuestUser } = sessionContainer
  //   // () => isRegisteredUser
  //   // const restrictedRoutes = ['/']
  //   // oneRouter.set('restrictedRoutes', restrictedRoutes)
  //   // if (oneRouter.isRestricted === true) {
  //   //   oneRouter.update('/login')
  //   // }
  // })
  // componentWillUnmount() {
  //   if (this.unsubscribeFromHistory) {
  //     this.unsubscribeFromHistory()
  //   }
  // }
  // handleLocationChange = location => {
  //   this.store.notifyRouteChange(location)
  // }
  // ===
  // componentWillReceiveProps(props) {
  //   // console.log('___PROPS___', JSON.stringify(props, null, 2))
  //   props = props || this.props
  //   oneRouter.props = clone(props)
  //   oneRouter.router = this.context.router || props.router
  //   oneRouter.history = oneRouter.history.router || oneRouter.history
  //   oneRouter.entries()
  // }
  render() {
    // @todo change this comment block to /** jsdoc */
    //
    // this.context assumes React.Router is provided ABOVE this
    // @note if ^ is not true, it is default `oneRouter` instance
    //
    // @todo how to ensure it does not need to be rendereed above?
    // 1. could render `<Router>` here
    // 2. could do minor update in `reference-store` in bootstrapper/container/Routing
    //    - this is how I did it before, just update container using consumer
    //    ^ it is even commented out
    // 3.  we COULD ALSO walk the tree until we find router and inject 1 below its
    const value = this.context

    // weird error...
    // return isFunction(this.props.children)
    //   ? <OneRouterContext.Provider value={value}>{this.props.children}</OneRouterContext.Provider>
    //   : null

    // @@debug
    return (
      <OneRouterContext.Provider value={value}>
        {this.props.children}
      </OneRouterContext.Provider>
    )
  }
}

/**
 * @alias OneRouterContainer
 * @note this is the top top top top level of our app
 * @note this was done this way when we were extracting props from old context (to scope props)
 */
const provideOneRouter = (_props: any) => {
  // <RouterContext>
  return React.createElement(OneRouterWrap, _props)
}

// not used? if it was, this should have `@withRouter`?
// this is basically `consume`
const withOneRouter = (Target: ComponentType) => {
  return class OneRouterWrapper extends React.Component {
    render() {
      const attributes = {
        ...oneRouter,
        ...this.props,
      }
      return <Target {...attributes} />
    }
  }
}

export {
  OneRouterContext,
  provideOneRouter as OneRouterContainer,
  OneRouterWrap as OneRouterProvider,
  provideOneRouter,
  withOneRouter,
  oneRouter,
  OneRouterWrap,
}