Skip to content

Commit 79b51a7

Browse files
committed
Component-centric API, horrors are encapsulated
1 parent 34d599a commit 79b51a7

File tree

6 files changed

+90
-72
lines changed

6 files changed

+90
-72
lines changed

examples/counter/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
"node-libs-browser": "^0.5.2",
2929
"react-dock": "^0.1.0",
3030
"react-hot-loader": "^1.3.0",
31-
"redux-devtools": "^3.0.0-alpha-7",
32-
"redux-devtools-log-monitor": "^1.0.0-alpha-7",
31+
"redux-devtools": "^3.0.0-alpha-8",
32+
"redux-devtools-log-monitor": "^1.0.0-alpha-8",
3333
"webpack": "^1.9.11",
3434
"webpack-dev-server": "^1.9.0"
3535
}
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import React from 'react';
12
import { createDevTools } from 'redux-devtools';
2-
import createLogMonitor from 'redux-devtools-log-monitor';
3-
import createDockMonitor from '../dock/DockMonitor';
3+
import LogMonitor from 'redux-devtools-log-monitor';
4+
import DockMonitor from '../dock/DockMonitor';
45

56
export default createDevTools(
6-
createDockMonitor(
7-
createLogMonitor()
8-
)
7+
<DockMonitor defaultPosition='bottom'>
8+
<LogMonitor theme='ocean' />
9+
</DockMonitor>
910
);

examples/counter/src/dock/DockMonitor.js

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,36 @@
22
// TODO: extract to a separate project.
33
//
44

5-
import React, { Component, PropTypes } from 'react';
5+
import React, { cloneElement, Children, Component, PropTypes } from 'react';
66
import Dock from 'react-dock';
77
import { combineReducers } from 'redux';
88

99
const POSITIONS = ['left', 'top', 'right', 'bottom'];
1010

11-
class DockMonitor extends Component {
11+
export default class DockMonitor extends Component {
1212
static propTypes = {
13+
defaultPosition: PropTypes.oneOf(POSITIONS).isRequired,
14+
defaultIsVisible: PropTypes.bool.isRequired,
15+
toggleVisibilityShortcut: PropTypes.string.isRequired,
16+
changePositionShortcut: PropTypes.string.isRequired,
17+
1318
monitorState: PropTypes.shape({
1419
position: PropTypes.oneOf(POSITIONS).isRequired,
1520
isVisible: PropTypes.bool.isRequired,
1621
child: PropTypes.any
17-
}).isRequired,
22+
}),
1823

1924
monitorActions: PropTypes.shape({
2025
toggleVisibility: PropTypes.func.isRequired,
2126
changePosition: PropTypes.func.isRequired
22-
}).isRequired
27+
})
28+
};
29+
30+
static defaultProps = {
31+
defaultIsVisible: true,
32+
defaultPosition: 'right',
33+
toggleVisibilityShortcut: 'H',
34+
changePositionShortcut: 'Q'
2335
};
2436

2537
componentDidMount() {
@@ -39,11 +51,11 @@ class DockMonitor extends Component {
3951

4052
const key = event.keyCode || event.which;
4153
const char = String.fromCharCode(key);
42-
switch (char) {
43-
case 'H':
54+
switch (char.toUpperCase()) {
55+
case this.props.toggleVisibilityShortcut.toUpperCase():
4456
this.props.monitorActions.toggleVisibility();
4557
break;
46-
case 'D':
58+
case this.props.changePositionShortcut.toUpperCase():
4759
this.props.monitorActions.changePosition();
4860
break;
4961
default:
@@ -52,13 +64,29 @@ class DockMonitor extends Component {
5264
}
5365

5466
render() {
55-
const { children, monitorState } = this.props;
56-
const { position, isVisible } = monitorState;
67+
const {
68+
monitorState,
69+
monitorActions,
70+
historyState,
71+
historyActions,
72+
children
73+
} = this.props;
74+
75+
const {
76+
position,
77+
isVisible
78+
} = monitorState;
79+
5780
return (
5881
<Dock position={position}
5982
isVisible={isVisible}
6083
dimMode='none'>
61-
{children}
84+
{cloneElement(Children.only(children), {
85+
monitorState: monitorState.child,
86+
monitorActions: monitorActions.child,
87+
historyState,
88+
historyActions
89+
})}
6290
</Dock>
6391
);
6492
}
@@ -74,43 +102,32 @@ function changePosition() {
74102
return { type: CHANGE_POSITION };
75103
}
76104

77-
export default function create(child, {
78-
defaultIsVisible = true,
79-
defaultPosition = 'right'
80-
} = {}) {
81-
function position(state = defaultPosition, action) {
105+
DockMonitor.setup = function setup(props) {
106+
function position(state = props.defaultPosition, action) {
82107
return (action.type === CHANGE_POSITION) ?
83108
POSITIONS[(POSITIONS.indexOf(state) + 1) % POSITIONS.length] :
84109
state;
85110
}
86111

87-
function isVisible(state = defaultIsVisible, action) {
112+
function isVisible(state = props.defaultIsVisible, action) {
88113
return (action.type === TOGGLE_VISIBILITY) ?
89114
!state :
90115
state;
91116
}
92117

93-
const ChildMonitor = child.component;
94-
const CompositeMonitor = ({ monitorState, monitorActions, ...rest }) => (
95-
<DockMonitor monitorState={monitorState}
96-
monitorActions={monitorActions}>
97-
<ChildMonitor {...rest}
98-
monitorState={monitorState.child}
99-
monitorActions={monitorActions.child} />
100-
</DockMonitor>
101-
);
118+
const child = Children.only(props.children);
119+
const childSetupResult = child.type.setup(child.props);
102120

103121
return {
104-
component: CompositeMonitor,
105122
reducer: combineReducers({
106123
position,
107124
isVisible,
108-
child: child.reducer
125+
child: childSetupResult.reducer
109126
}),
110127
actionCreators: {
111128
toggleVisibility,
112129
changePosition,
113-
child: child.actionCreators
130+
child: childSetupResult.actionCreators
114131
}
115132
};
116133
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redux-devtools",
3-
"version": "3.0.0-alpha-7",
3+
"version": "3.0.0-alpha-8",
44
"description": "Redux DevTools with hot reloading and time travel",
55
"main": "lib/index.js",
66
"scripts": {

src/connectMonitor.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/createDevTools.js

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,49 @@
1-
import React, { Component, PropTypes } from 'react';
2-
import instrument from './instrument';
3-
import connectMonitor from './connectMonitor';
1+
import React, { Children, Component, PropTypes } from 'react';
2+
import { connect } from 'react-redux';
3+
import { bindActionCreators } from 'redux';
4+
import bindActionCreatorsDeep from './bindActionCreatorsDeep';
5+
import instrument, { ActionCreators as historyActionCreators } from './instrument';
46

5-
export default function createDevTools(monitor) {
6-
const Monitor = connectMonitor(monitor);
7+
export default function createDevTools(children) {
8+
const child = Children.only(children);
9+
const { type: Monitor } = child;
10+
const { reducer, actionCreators } = Monitor.setup(child.props);
11+
12+
function mapStateToProps(state) {
13+
return {
14+
historyState: state.historyState,
15+
monitorState: state.monitorState
16+
};
17+
}
18+
19+
function mapDispatchToProps(dispatch) {
20+
return {
21+
historyActions: bindActionCreators(historyActionCreators, dispatch),
22+
monitorActions: bindActionCreatorsDeep(actionCreators, dispatch)
23+
};
24+
}
25+
26+
const ConnectedMonitor = connect(
27+
mapStateToProps,
28+
mapDispatchToProps
29+
)(Monitor);
730

831
return class DevTools extends Component {
932
static contextTypes = {
1033
store: PropTypes.object.isRequired
1134
};
1235

13-
static instrument = () => instrument(Monitor.reducer);
36+
static instrument = () => instrument(reducer);
37+
38+
constructor(props, context) {
39+
super(props, context);
40+
this.instrumentedStore = context.store.instrumentedStore;
41+
}
1442

1543
render() {
1644
return (
17-
<Monitor {...this.props}
18-
store={this.context.store.instrumentedStore} />
45+
<ConnectedMonitor {...child.props}
46+
store={this.instrumentedStore} />
1947
);
2048
}
2149
};

0 commit comments

Comments
 (0)