/
gredux.go
75 lines (64 loc) · 1.72 KB
/
gredux.go
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
package gredux
import (
"sync"
)
type (
// State is the state of the gredux Store.
State interface{}
// Reducer is the func which receives actions dispatched
// using Store.Dispatch() and updates the internal state.
Reducer func(State, Action) State
// Action defines a dispatchable data type that triggers updates in the Store.
Action struct {
ID string
Data interface{}
}
// Store defines an immutable store of state.
// The current state of the Store can be received by calling State()
// but the state can only be changed by a Reducer as the result of a Dispatch'd Action.
Store struct {
mu sync.RWMutex
reducer Reducer
state State
update func(State)
}
)
// New instantiates a new gredux Store.
// initialState should be the struct used to define the Store's state.
func New(initialState State) *Store {
st := Store{
reducer: func(s State, a Action) State {
return s
},
state: initialState,
}
return &st
}
// Reducer sets the store's reducer function to the function `r`.
func (st *Store) Reducer(r Reducer) {
st.reducer = r
}
// AfterUpdate sets Store's update func. `update` is called after each
// dispatch with a copy of the new state.
func (st *Store) AfterUpdate(update func(State)) {
st.update = update
}
// getState returns a copy of Store's current state map.
func (st *Store) getState() State {
return st.state
}
// State returns a copy of the current state.
func (st *Store) State() State {
st.mu.RLock()
defer st.mu.RUnlock()
return st.getState()
}
// Dispatch dispatches an Action into the Store.
func (st *Store) Dispatch(action Action) {
st.mu.Lock()
defer st.mu.Unlock()
st.state = st.reducer(st.getState(), action)
if st.update != nil {
st.update(st.getState())
}
}