import { Component, ValidationMap } from 'react'; import { History } from 'history'; import { Store, RouterStoreState } from './Store'; import * as PropTypes from 'prop-types'; import { Match, ValOrFunc, ToProps, NavParams, createNavParams } from './utils'; export type NavProviderPropsTyped

= { to: ToProps; match?: ValOrFunc; replace?: boolean; // render renderChild: (params: NavParams) => JSX.Element; noSubscribe?: boolean; }; export type NavProviderProps = NavProviderPropsTyped; export type NavProviderContext = { routerStore: Store; router: { history: History }; }; export class NavProvider extends Component { static displayName: string = 'NavProvider'; static contextTypes: ValidationMap = { routerStore: PropTypes.instanceOf(Store), // from RouterProvider or parent Route router: PropTypes.any, }; context: NavProviderContext; private unsubscribe: () => void; private isUnmounted: boolean = false; constructor(props: NavProviderProps, context: NavProviderContext) { super(props, context); if (!context.routerStore || !context.routerStore.getState() || !context.router || !context.router.history) { throw new Error('InjectMatch need a RouterProvider as ancestor'); } } componentDidMount() { if (this.props.noSubscribe !== true) { this.unsubscribe = this.context.routerStore.subscribe(() => { this.update(); }); } } UNSAFE_componentWillReceiveProps(nextProps: NavProviderProps): void { if (this.props.noSubscribe !== nextProps.noSubscribe) { if (nextProps.noSubscribe && this.unsubscribe) { this.unsubscribe(); } else { this.unsubscribe = this.context.routerStore.subscribe(() => { this.update(); }); } } } componentWillUnmount(): void { this.isUnmounted = true; if (this.unsubscribe) { this.unsubscribe(); } } render(): JSX.Element { const { renderChild, to, replace, match } = this.props; const parentRouterState: RouterStoreState = this.context.routerStore.getState(); const childParams: NavParams = createNavParams( to, this.context.router.history, parentRouterState.location, replace, match, parentRouterState.match, ); return renderChild(childParams); } private update(): void { if (this.isUnmounted === false) { this.forceUpdate(); } } }