import { Component, ValidationMap } from 'react';
import * as PropTypes from 'prop-types';
import { History, LocationDescriptorObject } from 'history';
import { Store, RouterStoreState } from './Store';
import { execValOrFunc, Match, ValOrFunc, checkSwitchState, ToProps, navigate, execTo } from './utils';
export type RedirectPropsTyped
= {
to: ToProps;
match?: ValOrFunc;
push?: boolean;
noSubscribe?: boolean;
switchIndex?: number;
};
export type RedirectProps = RedirectPropsTyped;
export type RedirectContext = {
routerStore: Store;
router: { history: History };
};
export class Redirect extends Component {
static displayName: string = 'Redirect';
static contextTypes: ValidationMap = {
routerStore: PropTypes.instanceOf(Store), // from RouterProvider or parent Route
router: PropTypes.any,
};
context: RedirectContext;
private unsubscribe: () => void;
constructor(props: RedirectProps, context: RedirectContext) {
super(props, context);
this.unsubscribe = context.routerStore.subscribe(() => {
this.update(this.props);
});
}
componentDidMount() {
if (this.props.noSubscribe !== true) {
this.unsubscribe = this.context.routerStore.subscribe(() => {
this.update(this.props);
});
}
this.update(this.props);
}
UNSAFE_componentWillReceiveProps(nextProps: RedirectProps): void {
this.update(nextProps);
}
render(): JSX.Element | null {
return null;
}
componentWillUnmount(): void {
if (this.unsubscribe) {
this.unsubscribe();
}
}
private update(props: RedirectProps): void {
const parentRouterState: RouterStoreState = this.context.routerStore.getState();
const match: Match = checkSwitchState(
props,
parentRouterState,
execValOrFunc(this.props.match, parentRouterState.location, parentRouterState.match),
);
const push: boolean = this.props.push === true;
if (match !== false) { // redirect
const toLocation: LocationDescriptorObject = execTo(
this.props.to,
match,
parentRouterState.location,
parentRouterState.match,
);
navigate(toLocation, this.context.router.history, !push);
}
}
}