/
counter.tsx
103 lines (87 loc) · 2.53 KB
/
counter.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import * as React from 'react'
import * as redux from 'redux'
import { connect } from 'react-redux'
import {
incrementCounter,
loadCount,
saveCount,
} from '../actions'
import { compose } from '../utils'
import { Action } from '../actions'
import * as state from '../reducers'
import loadable from '../decorators/loadable'
type OwnProps = {
}
type LoadingState = {
isSaving: boolean,
isLoading: boolean,
}
type ConnectedState = LoadingState & {
counter: { value: number }
error: string,
}
type ConnectedDispatch = {
increment: (n: number) => void
save: (n: number) => void
load: () => void
}
const mapStateToProps = (state: state.All, ownProps: OwnProps): ConnectedState => ({
counter: state.counter,
isSaving: state.isSaving,
isLoading: state.isLoading,
error: state.error,
})
const mapDispatchToProps = (dispatch: redux.Dispatch<Action>): ConnectedDispatch => ({
increment: (n: number) =>
dispatch(incrementCounter(n)),
load: () =>
loadCount({})(dispatch),
save: (value: number) =>
saveCount({ value })(dispatch),
})
export class PureCounter extends React.Component<ConnectedState & ConnectedDispatch & OwnProps, {}> {
_onClickIncrement = (e: React.SyntheticEvent<HTMLButtonElement>) => {
e.preventDefault()
this.props.increment(1)
}
_onClickSave = (e: React.SyntheticEvent<HTMLButtonElement>) => {
e.preventDefault()
if (!this.props.isSaving) {
this.props.save(this.props.counter.value)
}
}
_onClickLoad = (e: React.SyntheticEvent<HTMLButtonElement>) => {
e.preventDefault()
if (!this.props.isLoading) {
this.props.load()
}
}
render () {
const { counter, isSaving, isLoading, error } = this.props
return <div>
<div className='hero'>
<strong>{counter.value}</strong>
</div>
<form>
<button ref='increment' onClick={this._onClickIncrement}>click me!</button>
<button ref='save' disabled={isSaving} onClick={this._onClickSave}>{isSaving ? 'saving...' : 'save'}</button>
<button ref='load' disabled={isLoading} onClick={this._onClickLoad}>{ isLoading ? 'loading...' : 'load'}</button>
{ error ? <div className='error'>{error}</div> : null }
<pre>
{JSON.stringify({
counter,
isSaving,
isLoading,
}, null, 2)}
</pre>
</form>
</div>
}
}
const isLoading = (p: LoadingState) =>
p.isLoading || p.isSaving
export const Counter = compose(
PureCounter,
loadable(isLoading),
connect(mapStateToProps, mapDispatchToProps),
)