Skip to content

Commit 7b625a5

Browse files
authored
feat: Reducer traits (#18)
1 parent 72b6020 commit 7b625a5

File tree

3 files changed

+59
-8
lines changed

3 files changed

+59
-8
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/demo.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@ struct Data {
66
pub lists: Vec<Vec<String>>,
77
}
88

9+
pub enum ChannelAction {
10+
NewList,
11+
AddToList { list: usize, text: String },
12+
}
13+
14+
impl DataReducer for Data {
15+
type Action = ChannelAction;
16+
type Channel = DataChannel;
17+
18+
fn reduce(&mut self, message: Self::Action) -> Self::Channel {
19+
match message {
20+
ChannelAction::NewList => {
21+
self.lists.push(Vec::default());
22+
23+
DataChannel::ListCreated
24+
}
25+
ChannelAction::AddToList { list, text } => {
26+
self.lists[list].push(text);
27+
28+
DataChannel::ListN(list)
29+
}
30+
}
31+
}
32+
}
33+
934
#[derive(PartialEq, Eq, Clone, Debug)]
1035
pub enum DataChannel {
1136
ListCreated,
@@ -20,7 +45,7 @@ fn main() {
2045
let mut radio = use_radio::<Data, DataChannel>(DataChannel::ListCreated);
2146

2247
let onclick = move |_| {
23-
radio.write().lists.push(Vec::default());
48+
radio.apply(ChannelAction::NewList);
2449
};
2550

2651
println!("Running DataChannel::ListCreated");
@@ -49,7 +74,10 @@ fn ListComp(list_n: usize) -> Element {
4974
rsx!(
5075
div {
5176
button {
52-
onclick: move |_| radio.write().lists[list_n].push("Hello World".to_string()),
77+
onclick: move |_| radio.apply(ChannelAction::AddToList {
78+
list: 0,
79+
text: "Hello, World".to_string()
80+
}),
5381
"New Item"
5482
},
5583
ul {

src/hooks/use_radio.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,17 +357,14 @@ where
357357
/// }
358358
/// });
359359
/// ```
360-
pub fn write_with_map_channel(
361-
&mut self,
362-
cb: impl FnOnce(&mut RadioGuard<Value, Channel>) -> Channel,
363-
) {
360+
pub fn write_with_map_channel(&mut self, cb: impl FnOnce(&mut Value) -> Channel) {
364361
let value = self.antenna.peek().station.value.write_unchecked();
365362
let mut guard = RadioGuard {
366363
channels: Vec::default(),
367364
antenna: self.antenna,
368365
value,
369366
};
370-
let channel = cb(&mut guard);
367+
let channel = cb(&mut guard.value);
371368
for channel in channel.derive_channel(&guard.value) {
372369
self.antenna.peek().station.notify_listeners(&channel)
373370
}
@@ -419,3 +416,29 @@ where
419416
{
420417
use_context::<RadioStation<Value, Channel>>()
421418
}
419+
420+
pub trait DataReducer {
421+
type Channel;
422+
type Action;
423+
424+
fn reduce(&mut self, action: Self::Action) -> Self::Channel;
425+
}
426+
427+
pub trait RadioReducer {
428+
type Action;
429+
430+
fn apply(&mut self, action: Self::Action);
431+
}
432+
433+
impl<
434+
Data: DataReducer<Channel = Channel, Action = Action>,
435+
Channel: RadioChannel<Data>,
436+
Action,
437+
> RadioReducer for Radio<Data, Channel>
438+
{
439+
type Action = Action;
440+
441+
fn apply(&mut self, action: Action) {
442+
self.write_with_map_channel(|data| data.reduce(action));
443+
}
444+
}

0 commit comments

Comments
 (0)