forked from redux-rs/redux-rs
-
Notifications
You must be signed in to change notification settings - Fork 1
/
basic_todo.rs
114 lines (98 loc) · 2.83 KB
/
basic_todo.rs
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
104
105
106
107
108
109
110
111
112
113
114
// Implementation of a very basic todo list described on: https://redux.js.org/introduction/core-concepts/
// This example shows how to combine multiple reducers
use redux_rs::{Selector, Store};
// Javascript state:
//
// {
// todos: [{
// text: 'Eat food',
// completed: true
// }, {
// text: 'Exercise',
// completed: false
// }],
// visibilityFilter: 'SHOW_COMPLETED'
// }
//
// Rest equivalent:
#[derive(Default, Debug)]
struct State {
todos: Vec<Todo>,
visibility_filter: VisibilityFilter,
}
#[derive(Debug)]
struct Todo {
text: String,
completed: bool,
}
#[derive(Debug)]
enum VisibilityFilter {
ShowAll,
ShowCompleted,
}
impl Default for VisibilityFilter {
fn default() -> Self {
VisibilityFilter::ShowCompleted
}
}
enum Action {
AddTodo { text: String },
ToggleTodo { index: usize },
SetVisibilityFilter { filter: VisibilityFilter },
}
fn reducer(mut state: State, action: Action) -> State {
match action {
Action::AddTodo { text } => State {
todos: {
state.todos.push(Todo { text, completed: false });
state.todos
},
..state
},
Action::ToggleTodo { index } => State {
todos: {
if let Some(todo) = state.todos.get_mut(index) {
todo.completed = !todo.completed;
}
state.todos
},
..state
},
Action::SetVisibilityFilter { filter } => State {
visibility_filter: filter,
..state
},
}
}
struct SelectNumberCompletedTodos;
impl Selector<State> for SelectNumberCompletedTodos {
type Result = usize;
fn select(&self, state: &State) -> Self::Result {
state.todos.iter().filter(|t| t.completed).count()
}
}
#[tokio::main]
async fn main() {
let store = Store::new(reducer);
store.subscribe(|state: &State| println!("New state: {:?}", state)).await;
// Print number of completed tasks
println!("Number of completed tasks: {}", store.select(SelectNumberCompletedTodos).await);
// { type: 'ADD_TODO', text: 'Go to swimming pool' }
store
.dispatch(Action::AddTodo {
text: "Go to swimming pool".to_string(),
})
.await;
// Print number of completed tasks
println!("Number of completed tasks: {}", store.select(SelectNumberCompletedTodos).await);
// { type: 'TOGGLE_TODO', index: 0 }
store.dispatch(Action::ToggleTodo { index: 0 }).await;
// Print number of completed tasks
println!("Number of completed tasks: {}", store.select(SelectNumberCompletedTodos).await);
// { type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
store
.dispatch(Action::SetVisibilityFilter {
filter: VisibilityFilter::ShowAll,
})
.await;
}