|
1 | | -import React from 'react' |
2 | | -import initHistory from './history' |
3 | | -import {from} from 'most' |
4 | | -import mostEngine from './engine/most' |
5 | | -import mergeAll from 'ramda/src/mergeAll' |
6 | | -import pick from 'ramda/src/pick' |
7 | | -import keys from 'ramda/src/keys' |
| 1 | +import React from 'react'; |
| 2 | +import initHistory from './history'; |
| 3 | +import { from } from 'most'; |
| 4 | +import mostEngine from './engine/most'; |
| 5 | +import mergeAll from 'ramda/src/mergeAll'; |
| 6 | +import pick from 'ramda/src/pick'; |
| 7 | +import keys from 'ramda/src/keys'; |
8 | 8 | // unfortunately React doesn't support symbol as context key yet, so let me just preteding using Symbol until react implement the Symbol version of Object.assign |
9 | | -export const INTENT_STREAM = "@@reactive-react/react-most.intentStream"; |
10 | | -export const HISTORY_STREAM = "@@reactive-react/react-most.historyStream"; |
11 | | -const MERGE_OBSERVE = "@@reactive-react/react-most.mergeObserve"; |
| 9 | +export const INTENT_STREAM = '@@reactive-react/react-most.intentStream'; |
| 10 | +export const HISTORY_STREAM = '@@reactive-react/react-most.historyStream'; |
| 11 | +const MERGE_OBSERVE = '@@reactive-react/react-most.mergeObserve'; |
12 | 12 |
|
13 | 13 | const CONTEXT_TYPE = { |
14 | 14 | [INTENT_STREAM]: React.PropTypes.object, |
15 | 15 | [HISTORY_STREAM]: React.PropTypes.object, |
16 | 16 | [MERGE_OBSERVE]: React.PropTypes.func, |
17 | | -} |
| 17 | +}; |
18 | 18 |
|
19 | | -export function connect(main, opts={}) { |
20 | | - return function(WrappedComponent){ |
21 | | - let connectDisplayName = `Connect(${getDisplayName(WrappedComponent)})` |
| 19 | +export function connect(main, opts = {}) { |
| 20 | + return function(WrappedComponent) { |
| 21 | + let connectDisplayName = `Connect(${getDisplayName(WrappedComponent)})`; |
22 | 22 | if (WrappedComponent.contextTypes === CONTEXT_TYPE) { |
23 | 23 | class Connect extends React.PureComponent { |
24 | 24 | constructor(props, context) { |
25 | 25 | super(props, context); |
26 | | - let [actions, sink$] = actionsAndSinks(main(context[INTENT_STREAM],props), this) |
27 | | - this.sink$ = sink$.concat(props.sink$||[]) |
28 | | - this.actions = mergeAll([actions, props.actions]) |
| 26 | + let [actions, sink$] = actionsAndSinks( |
| 27 | + main(context[INTENT_STREAM], props), |
| 28 | + this |
| 29 | + ); |
| 30 | + this.sink$ = sink$.concat(props.sink$ || []); |
| 31 | + this.actions = mergeAll([actions, props.actions]); |
29 | 32 | } |
30 | | - render(){ |
31 | | - return <WrappedComponent {...this.props} {...opts} sink$={this.sink$} actions={this.actions}/> |
| 33 | + render() { |
| 34 | + return ( |
| 35 | + <WrappedComponent |
| 36 | + {...this.props} |
| 37 | + {...opts} |
| 38 | + sink$={this.sink$} |
| 39 | + actions={this.actions} |
| 40 | + /> |
| 41 | + ); |
32 | 42 | } |
33 | 43 | } |
34 | 44 | Connect.contextTypes = CONTEXT_TYPE; |
35 | 45 | Connect.displayName = connectDisplayName; |
36 | 46 | return Connect; |
37 | | - }else{ |
| 47 | + } else { |
38 | 48 | class Connect extends React.PureComponent { |
39 | 49 | constructor(props, context) { |
40 | 50 | super(props, context); |
41 | | - if(opts.history || props.history){ |
42 | | - opts.history = initHistory(context[HISTORY_STREAM]) |
43 | | - opts.history.travel.forEach(state=>{ |
44 | | - return this.setState(state) |
45 | | - }) |
| 51 | + if (opts.history || props.history) { |
| 52 | + opts.history = initHistory(context[HISTORY_STREAM]); |
| 53 | + opts.history.travel.forEach(state => { |
| 54 | + return this.setState(state); |
| 55 | + }); |
46 | 56 | } |
47 | 57 |
|
48 | | - let [actions, sink$] = actionsAndSinks(main(context[INTENT_STREAM],props), this) |
49 | | - this.sink$ = sink$.concat(props.sink$||[]) |
50 | | - this.actions = mergeAll([actions, props.actions]) |
51 | | - let defaultKey = keys(WrappedComponent.defaultProps) |
52 | | - this.state = mergeAll([WrappedComponent.defaultProps, pick(defaultKey, props)]) |
| 58 | + let [actions, sink$] = actionsAndSinks( |
| 59 | + main(context[INTENT_STREAM], props), |
| 60 | + this |
| 61 | + ); |
| 62 | + this.sink$ = sink$.concat(props.sink$ || []); |
| 63 | + this.actions = mergeAll([actions, props.actions]); |
| 64 | + let defaultKey = keys(WrappedComponent.defaultProps); |
| 65 | + this.state = mergeAll([ |
| 66 | + WrappedComponent.defaultProps, |
| 67 | + pick(defaultKey, props), |
| 68 | + ]); |
53 | 69 | } |
54 | | - componentWillReceiveProps(nextProps){ |
55 | | - this.setState(state=>pick(keys(state), nextProps)) |
| 70 | + componentWillReceiveProps(nextProps) { |
| 71 | + this.setState(state => pick(keys(state), nextProps)); |
56 | 72 | } |
57 | | - componentDidMount(){ |
58 | | - this.subscriptions = this.context[MERGE_OBSERVE](this.sink$, (action)=>{ |
59 | | - if(action instanceof Function) { |
60 | | - this.setState((prevState, props)=>{ |
61 | | - let newState = action.call(this, prevState,props); |
62 | | - if(opts.history && newState != prevState){ |
63 | | - opts.history.cursor = -1; |
64 | | - this.context[HISTORY_STREAM].send(prevState); |
65 | | - } |
66 | | - return newState; |
67 | | - }); |
68 | | - } else { |
69 | | - /* istanbul ignore next */ |
70 | | - console.warn('action', action,'need to be a Function which map from current state to new state'); |
| 73 | + componentDidMount() { |
| 74 | + this.subscriptions = this.context[MERGE_OBSERVE]( |
| 75 | + this.sink$, |
| 76 | + action => { |
| 77 | + if (action instanceof Function) { |
| 78 | + this.setState((prevState, props) => { |
| 79 | + let newState = action.call(this, prevState, props); |
| 80 | + if (opts.history && newState != prevState) { |
| 81 | + opts.history.cursor = -1; |
| 82 | + this.context[HISTORY_STREAM].send(prevState); |
| 83 | + } |
| 84 | + return newState; |
| 85 | + }); |
| 86 | + } else { |
| 87 | + /* istanbul ignore next */ |
| 88 | + console.warn( |
| 89 | + 'action', |
| 90 | + action, |
| 91 | + 'need to be a Function which map from current state to new state' |
| 92 | + ); |
| 93 | + } |
71 | 94 | } |
72 | | - }); |
| 95 | + ); |
73 | 96 | } |
74 | | - componentWillUnmount(){ |
75 | | - this.subscriptions.unsubscribe() |
| 97 | + componentWillUnmount() { |
| 98 | + this.subscriptions.unsubscribe(); |
76 | 99 | } |
77 | 100 | render() { |
78 | | - return <WrappedComponent {...this.props} {...this.state} {...opts} actions={this.actions} /> |
| 101 | + return ( |
| 102 | + <WrappedComponent |
| 103 | + {...this.props} |
| 104 | + {...this.state} |
| 105 | + {...opts} |
| 106 | + actions={this.actions} |
| 107 | + /> |
| 108 | + ); |
79 | 109 | } |
80 | 110 | } |
81 | 111 | Connect.contextTypes = CONTEXT_TYPE; |
82 | 112 | Connect.displayName = connectDisplayName; |
83 | 113 | return Connect; |
84 | 114 | } |
85 | | - } |
| 115 | + }; |
86 | 116 | } |
87 | 117 |
|
88 | 118 | let Most = React.createClass({ |
89 | 119 | childContextTypes: CONTEXT_TYPE, |
90 | | - getChildContext(){ |
91 | | - let engineClass = this.props && this.props.engine || mostEngine |
| 120 | + getChildContext() { |
| 121 | + let engineClass = (this.props && this.props.engine) || mostEngine; |
92 | 122 | let engine = engineClass(); |
93 | 123 | /* istanbul ignore if */ |
94 | | - if(process.env.NODE_ENV==='debug') { |
95 | | - inspect(engine) |
| 124 | + if (process.env.NODE_ENV === 'debug') { |
| 125 | + inspect(engine); |
96 | 126 | } |
97 | 127 | return { |
98 | 128 | [INTENT_STREAM]: engine.intentStream, |
99 | 129 | [MERGE_OBSERVE]: engine.mergeObserve, |
100 | 130 | [HISTORY_STREAM]: engine.historyStream, |
101 | | - } |
| 131 | + }; |
102 | 132 | }, |
103 | 133 | render() { |
104 | 134 | return React.Children.only(this.props.children); |
105 | | - } |
| 135 | + }, |
106 | 136 | }); |
107 | 137 |
|
108 | 138 | export default Most; |
109 | 139 |
|
110 | | -function observable(obj){ |
111 | | - return !!obj.subscribe |
| 140 | +function observable(obj) { |
| 141 | + return !!obj.subscribe; |
112 | 142 | } |
113 | 143 |
|
114 | 144 | /* istanbul ignore next */ |
115 | 145 | function inspect(engine) { |
116 | | - from(engine.intentStream).timestamp() |
117 | | - .observe(stamp=>console.log(`[${new Date(stamp.time).toJSON()}][INTENT]:}`, stamp.value)); |
118 | | - from(engine.historyStream).timestamp() |
119 | | - .observe(stamp=>console.log(`[${new Date(stamp.time).toJSON()}][STATE]:}`, stamp.value)); |
| 146 | + from(engine.intentStream) |
| 147 | + .timestamp() |
| 148 | + .observe(stamp => |
| 149 | + console.log(`[${new Date(stamp.time).toJSON()}][INTENT]:}`, stamp.value) |
| 150 | + ); |
| 151 | + from(engine.historyStream) |
| 152 | + .timestamp() |
| 153 | + .observe(stamp => |
| 154 | + console.log(`[${new Date(stamp.time).toJSON()}][STATE]:}`, stamp.value) |
| 155 | + ); |
120 | 156 | } |
121 | 157 |
|
122 | | -function actionsAndSinks(sinks, self){ |
| 158 | +function actionsAndSinks(sinks, self) { |
123 | 159 | let _sinks = []; |
124 | 160 | let _actions = { |
125 | | - fromEvent(e, f=x=>x){ |
| 161 | + fromEvent(e, f = x => x) { |
126 | 162 | return self.context[INTENT_STREAM].send(f(e)); |
127 | 163 | }, |
128 | | - fromPromise(p){ |
129 | | - return p.then(x=>self.context[INTENT_STREAM].send(x)); |
130 | | - } |
| 164 | + fromPromise(p) { |
| 165 | + return p.then(x => self.context[INTENT_STREAM].send(x)); |
| 166 | + }, |
131 | 167 | }; |
132 | | - for(let name in sinks){ |
133 | | - let value = sinks[name] |
134 | | - if(observable(value)){ |
| 168 | + for (let name in sinks) { |
| 169 | + let value = sinks[name]; |
| 170 | + if (observable(value)) { |
135 | 171 | _sinks.push(value); |
136 | | - } else if(value instanceof Function){ |
137 | | - _actions[name] = (...args)=>{ |
| 172 | + } else if (value instanceof Function) { |
| 173 | + _actions[name] = (...args) => { |
138 | 174 | return self.context[INTENT_STREAM].send(value.apply(self, args)); |
139 | | - } |
140 | | - } else if(name === 'actions') { |
141 | | - for(let a in value) |
142 | | - _actions[a] = (...args)=>{ |
| 175 | + }; |
| 176 | + } else if (name === 'actions') { |
| 177 | + for (let a in value) |
| 178 | + _actions[a] = (...args) => { |
143 | 179 | return self.context[INTENT_STREAM].send(value[a].apply(self, args)); |
144 | | - } |
| 180 | + }; |
145 | 181 | } |
146 | 182 | } |
147 | | - return [_actions, _sinks] |
| 183 | + return [_actions, _sinks]; |
148 | 184 | } |
149 | 185 |
|
150 | 186 | function getDisplayName(WrappedComponent) { |
151 | | - return WrappedComponent.displayName || WrappedComponent.name || 'Component' |
| 187 | + return WrappedComponent.displayName || WrappedComponent.name || 'Component'; |
152 | 188 | } |
0 commit comments