import React , { Children , Component } from 'react' ; import PropTypes from 'prop-types' ; import { connect , Provider , ReactReduxContext } from 'react-redux' ; import { instrument , EnhancedStore , LiftedState , LiftedStore , Options , } from '@redux-devtools/instrument' ; import { Action } from 'redux' ; function logError ( type ) { if ( type === 'NoStore' ) { console . error ( 'Redux DevTools could not render. You must pass the Redux store ' + 'to <DevTools> either as a "store" prop or by wrapping it in a ' + '<Provider store={store}>.' ) ; } else { console . error ( 'Redux DevTools could not render. Did you forget to include ' + 'DevTools.instrument() in your store enhancer chain before ' + 'using createStore()?' ) ; } } export interface Props < S , A extends Action < unknown > , MonitorState , MonitorAction extends Action < unknown > > { store ? : EnhancedStore < S , A , MonitorState > ; } export type Monitor < S , A extends Action < unknown > , MonitorProps extends LiftedState < S , A , MonitorState > , MonitorState , MonitorAction extends Action < unknown > > = React . ReactElement < MonitorProps , React . ComponentType < MonitorProps & LiftedState < S , A , MonitorState > > & { update ( monitorProps , state , action ) : MonitorState ; } > ; export default function createDevTools < S , A extends Action < unknown > , MonitorProps extends LiftedState < S , A , MonitorState > , MonitorState , MonitorAction extends Action < unknown > > ( children ) { const monitorElement = Children . only ( children ) ; const monitorProps = monitorElement . props ; const Monitor = monitorElement . type ; const ConnectedMonitor = connect ( ( state ) => state ) ( Monitor as React . ComponentType < any > ) ; return class DevTools extends Component < Props < S , A , MonitorState , MonitorAction > > { static contextTypes = { store : PropTypes . object , } ; static propTypes = { store : PropTypes . object , } ; liftedStore ? : LiftedStore < S , A , MonitorState > ; static instrument = ( options ? ) => instrument ( ( state , action ) => Monitor . update ( monitorProps , state , action ) , options ) ; constructor ( props , context ) { super ( props , context ) ; if ( ReactReduxContext ) { if ( this . props . store && ! this . props . store . liftedStore ) { logError ( 'NoLiftedStore' ) ; } return ; } if ( ! props . store && ! context . store ) { logError ( 'NoStore' ) ; return ; } if ( context . store ) { this . liftedStore = context . store . liftedStore ; } else { this . liftedStore = props . store ! . liftedStore ; } if ( ! this . liftedStore ) { logError ( 'NoLiftedStore' ) ; } } render ( ) { if ( ReactReduxContext ) { if ( this . props . store ) { if ( ! this . props . store . liftedStore ) { return null ; } return ( < Provider store = { this . props . store . liftedStore } > < ConnectedMonitor { ... monitorProps } / > < /Provider>); } return ( < ReactReduxContext . Consumer > { ( props ) => { if ( ! props || ! props . store ) { logError ( 'NoStore' ) ; return null ; } if ( ! ( props . store as unknown as EnhancedStore < S , A , MonitorState > ) . liftedStore ) { logError ( 'NoLiftedStore' ) ; return null ; } return ( < Provider store = { ( props . store as unknown as EnhancedStore < S , A , MonitorState > ) . liftedStore } > < ConnectedMonitor { ... monitorProps } / > < /Provider>); } } < /ReactReduxContext.Consumer>); } if ( ! this . liftedStore ) { return null ; } return < ConnectedMonitor { ... monitorProps } store = { this . liftedStore } / > ; } } ; }