mirror of
				https://github.com/reduxjs/redux-devtools.git
				synced 2025-10-31 16:07:45 +03:00 
			
		
		
		
	Explicit > implicit
This commit is contained in:
		
							parent
							
								
									b2210f161c
								
							
						
					
					
						commit
						4375d69d5e
					
				
							
								
								
									
										10
									
								
								examples/counter/src/containers/DevTools.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								examples/counter/src/containers/DevTools.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | import React from 'react'; | ||||||
|  | import { createDevTools } from 'redux-devtools'; | ||||||
|  | import createLogMonitor from 'redux-devtools-log-monitor'; | ||||||
|  | import createDockMonitor from '../dock/DockMonitor'; | ||||||
|  | 
 | ||||||
|  | export default createDevTools( | ||||||
|  |   createDockMonitor( | ||||||
|  |     createLogMonitor() | ||||||
|  |   ) | ||||||
|  | ); | ||||||
|  | @ -1,24 +1,18 @@ | ||||||
| import React, { Component } from 'react'; | import React, { Component } from 'react'; | ||||||
| import { Provider } from 'react-redux'; | import { Provider } from 'react-redux'; | ||||||
| import { DevToolsProvider } from 'redux-devtools'; |  | ||||||
| import CounterApp from './CounterApp'; | import CounterApp from './CounterApp'; | ||||||
| import LogMonitor from 'redux-devtools-log-monitor'; | import DevTools from './DevTools'; | ||||||
| import DockMonitor from '../dock/DockMonitor'; |  | ||||||
| 
 | 
 | ||||||
| export default class Root extends Component { | export default class Root extends Component { | ||||||
|   render() { |   render() { | ||||||
|     const { store } = this.props; |     const { store } = this.props; | ||||||
|     return ( |     return ( | ||||||
|       <div> |       <Provider store={store}> | ||||||
|         <Provider store={store}> |         <div> | ||||||
|           <CounterApp /> |           <CounterApp /> | ||||||
|         </Provider> |           <DevTools /> | ||||||
|         <DevToolsProvider store={store}> |         </div> | ||||||
|           <DockMonitor> |       </Provider> | ||||||
|             <LogMonitor /> |  | ||||||
|           </DockMonitor> |  | ||||||
|         </DevToolsProvider> |  | ||||||
|       </div> |  | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,65 +4,23 @@ | ||||||
| 
 | 
 | ||||||
| import React, { Component, PropTypes } from 'react'; | import React, { Component, PropTypes } from 'react'; | ||||||
| import Dock from 'react-dock'; | import Dock from 'react-dock'; | ||||||
| import MapProvider from './MapProvider'; |  | ||||||
| import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||||
| import { combineReducers } from 'redux'; | import { combineReducers, bindActionCreators } from 'redux'; | ||||||
| 
 |  | ||||||
| const TOGGLE_VISIBILITY = '@@redux-devtools/dock/TOGGLE_VISIBILITY'; |  | ||||||
| function toggleVisibility() { |  | ||||||
|   return { type: TOGGLE_VISIBILITY }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const CHANGE_POSITION = '@@redux-devtools/dock/CHANGE_POSITION'; |  | ||||||
| function changePosition() { |  | ||||||
|   return { type: CHANGE_POSITION }; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| const POSITIONS = ['left', 'top', 'right', 'bottom']; | const POSITIONS = ['left', 'top', 'right', 'bottom']; | ||||||
| 
 | 
 | ||||||
| function wrapReducer(options = {}) { | class DockMonitor extends Component { | ||||||
|   const { |  | ||||||
|     isVisible: initialIsVisible = true, |  | ||||||
|     position: initialPosition = 'right' |  | ||||||
|   } = options; |  | ||||||
| 
 |  | ||||||
|   function position(state = initialPosition, action) { |  | ||||||
|     return (action.type === CHANGE_POSITION) ? |  | ||||||
|       POSITIONS[(POSITIONS.indexOf(state) + 1) % POSITIONS.length] : |  | ||||||
|       state; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function isVisible(state = initialIsVisible, action) { |  | ||||||
|     return (action.type === TOGGLE_VISIBILITY) ? |  | ||||||
|       !state : |  | ||||||
|       state; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return childMonitorReducer => combineReducers({ |  | ||||||
|     childMonitorState: childMonitorReducer, |  | ||||||
|     position, |  | ||||||
|     isVisible |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function mapUpstreamStateToDownstreamState(state) { |  | ||||||
|   return { |  | ||||||
|     devToolsState: state.devToolsState, |  | ||||||
|     monitorState: state.monitorState.childMonitorState |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| @connect( |  | ||||||
|   state => state.monitorState, |  | ||||||
|   { toggleVisibility, changePosition } |  | ||||||
| ) |  | ||||||
| export default class DockMonitor extends Component { |  | ||||||
|   static propTypes = { |   static propTypes = { | ||||||
|     position: PropTypes.oneOf(['left', 'top', 'right', 'bottom']).isRequired, |     monitorState: PropTypes.shape({ | ||||||
|     isVisible: PropTypes.bool.isRequired, |       position: PropTypes.oneOf(POSITIONS).isRequired, | ||||||
|     childMonitorState: PropTypes.any, |       isVisible: PropTypes.bool.isRequired, | ||||||
|     toggleVisibility: PropTypes.func.isRequired, |       childState: PropTypes.any | ||||||
|     changePosition: PropTypes.func.isRequired |     }).isRequired, | ||||||
|  | 
 | ||||||
|  |     monitorActions: PropTypes.shape({ | ||||||
|  |       toggleVisibility: PropTypes.func.isRequired, | ||||||
|  |       changePosition: PropTypes.func.isRequired | ||||||
|  |     }).isRequired | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   componentDidMount() { |   componentDidMount() { | ||||||
|  | @ -84,10 +42,10 @@ export default class DockMonitor extends Component { | ||||||
|     const char = String.fromCharCode(key); |     const char = String.fromCharCode(key); | ||||||
|     switch (char) { |     switch (char) { | ||||||
|     case 'H': |     case 'H': | ||||||
|       this.props.toggleVisibility(); |       this.props.monitorActions.toggleVisibility(); | ||||||
|       break; |       break; | ||||||
|     case 'D': |     case 'D': | ||||||
|       this.props.changePosition(); |       this.props.monitorActions.changePosition(); | ||||||
|       break; |       break; | ||||||
|     default: |     default: | ||||||
|       break; |       break; | ||||||
|  | @ -95,17 +53,75 @@ export default class DockMonitor extends Component { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { position, isVisible, children } = this.props; |     const { children, monitorState } = this.props; | ||||||
|  |     const { position, isVisible } = monitorState; | ||||||
|     return ( |     return ( | ||||||
|       <Dock position={position} |       <Dock position={position} | ||||||
|             isVisible={isVisible} |             isVisible={isVisible} | ||||||
|             dimMode='none'> |             dimMode='none'> | ||||||
|         <MapProvider mapState={mapUpstreamStateToDownstreamState}> |         {children} | ||||||
|           {children} |  | ||||||
|         </MapProvider> |  | ||||||
|       </Dock> |       </Dock> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DockMonitor.wrapReducer = wrapReducer; | const TOGGLE_VISIBILITY = '@@redux-devtools/dock/TOGGLE_VISIBILITY'; | ||||||
|  | function toggleVisibility() { | ||||||
|  |   return { type: TOGGLE_VISIBILITY }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const CHANGE_POSITION = '@@redux-devtools/dock/CHANGE_POSITION'; | ||||||
|  | function changePosition() { | ||||||
|  |   return { type: CHANGE_POSITION }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default function create(ChildMonitor, { | ||||||
|  |   defaultIsVisible = true, | ||||||
|  |   defaultPosition = 'right' | ||||||
|  | } = {}) { | ||||||
|  |   function position(state = defaultPosition, action) { | ||||||
|  |     return (action.type === CHANGE_POSITION) ? | ||||||
|  |       POSITIONS[(POSITIONS.indexOf(state) + 1) % POSITIONS.length] : | ||||||
|  |       state; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function isVisible(state = defaultIsVisible, action) { | ||||||
|  |     return (action.type === TOGGLE_VISIBILITY) ? | ||||||
|  |       !state : | ||||||
|  |       state; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function getChildStore(store) { | ||||||
|  |     return { | ||||||
|  |       ...store, | ||||||
|  |       getState() { | ||||||
|  |         const state = store.getState(); | ||||||
|  |         return { | ||||||
|  |           ...state, | ||||||
|  |           monitorState: state.monitorState.childState | ||||||
|  |         }; | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const Monitor = connect( | ||||||
|  |     state => state, | ||||||
|  |     dispatch => ({ | ||||||
|  |       monitorActions: bindActionCreators({ toggleVisibility, changePosition }, dispatch) | ||||||
|  |     }) | ||||||
|  |   )(DockMonitor); | ||||||
|  | 
 | ||||||
|  |   const CompositeMonitor = ({ store }) => ( | ||||||
|  |     <Monitor store={store}> | ||||||
|  |       <ChildMonitor store={getChildStore(store)} /> | ||||||
|  |     </Monitor> | ||||||
|  |   ); | ||||||
|  | 
 | ||||||
|  |   CompositeMonitor.reducer = combineReducers({ | ||||||
|  |     childState: ChildMonitor.reducer, | ||||||
|  |     position, | ||||||
|  |     isVisible | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   return CompositeMonitor; | ||||||
|  | } | ||||||
|  | @ -1,52 +0,0 @@ | ||||||
| //
 |  | ||||||
| // TODO: extract to a separate project.
 |  | ||||||
| //
 |  | ||||||
| 
 |  | ||||||
| import { Children, Component, PropTypes } from 'react'; |  | ||||||
| 
 |  | ||||||
| const identity = _ => _; |  | ||||||
| function mapStore(store, { mapAction = identity, mapState = identity }) { |  | ||||||
|   return { |  | ||||||
|     ...store, |  | ||||||
|     dispatch(action) { |  | ||||||
|       return store.dispatch(mapAction(action)); |  | ||||||
|     }, |  | ||||||
|     subscribe(listener) { |  | ||||||
|       return store.subscribe(listener); |  | ||||||
|     }, |  | ||||||
|     getState() { |  | ||||||
|       return mapState(store.getState()); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export default class MapProvider extends Component { |  | ||||||
|   static propTypes = { |  | ||||||
|     mapAction: PropTypes.func, |  | ||||||
|     mapState: PropTypes.func |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   static contextTypes = { |  | ||||||
|     store: PropTypes.object.isRequired |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   static childContextTypes = { |  | ||||||
|     store: PropTypes.object.isRequired |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   getChildContext() { |  | ||||||
|     return { |  | ||||||
|       store: this.store |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   constructor(props, context) { |  | ||||||
|     super(props, context); |  | ||||||
|     this.store = mapStore(context.store, props); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   render() { |  | ||||||
|     return Children.only(this.props.children); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  | @ -1,23 +1,12 @@ | ||||||
| import { createStore, applyMiddleware, compose } from 'redux'; | import { createStore, applyMiddleware, compose } from 'redux'; | ||||||
| import devTools, { persistState } from 'redux-devtools'; | import { persistState } from 'redux-devtools'; | ||||||
| import thunk from 'redux-thunk'; | import thunk from 'redux-thunk'; | ||||||
| import rootReducer from '../reducers'; | import rootReducer from '../reducers'; | ||||||
| import DockMonitor from '../dock/DockMonitor'; | import DevTools from '../containers/DevTools'; | ||||||
| import LogMonitor from 'redux-devtools-log-monitor'; |  | ||||||
| 
 | 
 | ||||||
| const finalCreateStore = compose( | const finalCreateStore = compose( | ||||||
|   applyMiddleware( |   applyMiddleware(thunk), | ||||||
|     thunk |   DevTools.enhance, | ||||||
|   ), |  | ||||||
|   devTools( |  | ||||||
|     LogMonitor.createReducer({ |  | ||||||
|       preserveScrollTop: true |  | ||||||
|     }), |  | ||||||
|     DockMonitor.wrapReducer({ |  | ||||||
|       position: 'right', |  | ||||||
|       isVisible: true |  | ||||||
|     }) |  | ||||||
|   ), |  | ||||||
|   persistState( |   persistState( | ||||||
|     window.location.href.match( |     window.location.href.match( | ||||||
|       /[?&]debug_session=([^&]+)\b/ |       /[?&]debug_session=([^&]+)\b/ | ||||||
|  |  | ||||||
|  | @ -1,37 +0,0 @@ | ||||||
| import React, { Component } from 'react'; |  | ||||||
| import { Provider } from 'react-redux'; |  | ||||||
| 
 |  | ||||||
| export default class DevToolsProvider extends Component { |  | ||||||
|   static propTypes = { |  | ||||||
|     store(props, propName, componentName) { |  | ||||||
|       if (!props.store) { |  | ||||||
|         return new Error('Required prop `store` was not specified in `' + componentName + '`.'); |  | ||||||
|       } |  | ||||||
|       if (!props.store.devToolsStore) { |  | ||||||
|         return new Error( |  | ||||||
|           'Could not find the DevTools store inside the `store` prop passed to `' + |  | ||||||
|           componentName + |  | ||||||
|           '`. Have you applied the devTools() store enhancer?' |  | ||||||
|         ); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   render() { |  | ||||||
|     const { store, children } = this.props; |  | ||||||
|     if (!store) { |  | ||||||
|       return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const { devToolsStore } = store; |  | ||||||
|     if (!devToolsStore) { |  | ||||||
|       return null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ( |  | ||||||
|       <Provider store={devToolsStore}> |  | ||||||
|         {children} |  | ||||||
|       </Provider> |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										17
									
								
								src/createDevTools.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/createDevTools.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | import React, { cloneElement, Component, PropTypes } from 'react'; | ||||||
|  | import enhance from './enhance'; | ||||||
|  | 
 | ||||||
|  | export default function createDevTools(Monitor) { | ||||||
|  |   return class DevTools extends Component { | ||||||
|  |     static contextTypes = { | ||||||
|  |       store: PropTypes.object.isRequired | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     static enhance = enhance(Monitor.reducer); | ||||||
|  | 
 | ||||||
|  |     render() { | ||||||
|  |       return <Monitor store={this.context.store.devToolsStore} />; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -264,18 +264,11 @@ export const ActionCreators = { | ||||||
| /** | /** | ||||||
|  * Redux DevTools store enhancer. |  * Redux DevTools store enhancer. | ||||||
|  */ |  */ | ||||||
| export default function devTools( | export default function enhance(monitorReducer = () => null) { | ||||||
|   monitorReducer = () => null, |  | ||||||
|   ...monitorReducerWrappers |  | ||||||
| ) { |  | ||||||
|   return next => (reducer, initialState) => { |   return next => (reducer, initialState) => { | ||||||
|     const finalMonitorReducer = compose( |  | ||||||
|       ...monitorReducerWrappers.slice().reverse() |  | ||||||
|     )(monitorReducer); |  | ||||||
| 
 |  | ||||||
|     const wrapReducer = (r) => combineReducers({ |     const wrapReducer = (r) => combineReducers({ | ||||||
|       devToolsState: createDevToolsStateReducer(r, initialState), |       devToolsState: createDevToolsStateReducer(r, initialState), | ||||||
|       monitorState: finalMonitorReducer |       monitorState: monitorReducer | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     const devToolsStore = next(wrapReducer(reducer)); |     const devToolsStore = next(wrapReducer(reducer)); | ||||||
|  | @ -1,3 +1,3 @@ | ||||||
| export { default, ActionCreators, ActionTypes } from './devTools'; | export { default, ActionCreators, ActionTypes } from './enhance'; | ||||||
| export { default as DevToolsProvider } from './DevToolsProvider'; |  | ||||||
| export { default as persistState } from './persistState'; | export { default as persistState } from './persistState'; | ||||||
|  | export { default as createDevTools } from './createDevTools'; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user