redux-devtools/packages/redux-devtools-app/src/containers/DevTools.tsx

120 lines
3.2 KiB
TypeScript
Raw Normal View History

2019-01-10 20:23:33 +03:00
import React, { Component } from 'react';
2019-01-03 17:14:25 +03:00
import { withTheme } from 'styled-components';
import { LiftedAction, LiftedState } from '@redux-devtools/core';
import { Action } from 'redux';
2019-01-03 17:14:25 +03:00
import getMonitor from '../utils/getMonitor';
import { InitMonitorAction } from '../actions';
import { Features, State } from '../reducers/instances';
import { MonitorStateMonitorState } from '../reducers/monitor';
import { ThemeFromProvider } from '@redux-devtools/ui';
2019-01-03 17:14:25 +03:00
interface Props {
monitor: string;
liftedState: State;
monitorState: MonitorStateMonitorState | undefined;
dispatch: (
action: LiftedAction<unknown, Action<unknown>, unknown> | InitMonitorAction
) => void;
features: Features | undefined;
theme: ThemeFromProvider;
}
class DevTools extends Component<Props> {
monitorProps: unknown;
Monitor?: React.ComponentType<
LiftedState<unknown, Action<unknown>, unknown>
> & {
update(
monitorProps: unknown,
state: unknown | undefined,
action: Action<unknown>
): unknown;
};
preventRender?: boolean;
constructor(props: Props) {
2019-01-03 17:14:25 +03:00
super(props);
this.getMonitor(props, props.monitorState);
}
getMonitor(props: Props, skipUpdate?: unknown) {
2019-01-03 17:14:25 +03:00
const monitorElement = getMonitor(props);
this.monitorProps = monitorElement.props;
this.Monitor = monitorElement.type;
// eslint-disable-next-line @typescript-eslint/unbound-method
const update = this.Monitor!.update;
2019-01-03 17:14:25 +03:00
if (update) {
let newMonitorState;
const monitorState = props.monitorState;
2019-01-10 21:51:14 +03:00
if (
skipUpdate ||
(monitorState && monitorState.__overwritten__ === props.monitor)
) {
2019-01-03 17:14:25 +03:00
newMonitorState = monitorState;
} else {
newMonitorState = update(
this.monitorProps,
undefined,
{} as Action<unknown>
);
2019-01-03 17:14:25 +03:00
if (newMonitorState !== monitorState) {
this.preventRender = true;
}
}
this.dispatch({
type: '@@INIT_MONITOR',
newMonitorState,
update,
monitorProps: this.monitorProps,
2019-01-03 17:14:25 +03:00
});
}
}
UNSAFE_componentWillUpdate(nextProps: Props) {
2019-01-03 17:14:25 +03:00
if (nextProps.monitor !== this.props.monitor) this.getMonitor(nextProps);
}
shouldComponentUpdate(nextProps: Props) {
2019-01-03 17:14:25 +03:00
return (
nextProps.monitor !== this.props.monitor ||
nextProps.liftedState !== this.props.liftedState ||
nextProps.monitorState !== this.props.monitorState ||
2019-01-03 17:14:25 +03:00
nextProps.features !== this.props.features ||
nextProps.theme.scheme !== this.props.theme.scheme
);
}
dispatch = (
action: LiftedAction<unknown, Action<unknown>, unknown> | InitMonitorAction
) => {
2019-01-03 17:14:25 +03:00
this.props.dispatch(action);
};
render() {
if (this.preventRender) {
this.preventRender = false;
return null;
}
const liftedState = {
...this.props.liftedState,
monitorState: this.props.monitorState,
2019-01-03 17:14:25 +03:00
};
const MonitorAsAny = this.Monitor as any;
2019-01-03 17:14:25 +03:00
return (
<div className={`monitor monitor-${this.props.monitor}`}>
<MonitorAsAny
2019-01-03 17:14:25 +03:00
{...liftedState}
{...this.monitorProps}
features={this.props.features}
dispatch={this.dispatch}
theme={this.props.theme}
/>
</div>
);
}
}
export default withTheme(DevTools);