Closed SecondFlight closed 2 years ago
At this point what you're doing is the only option. Similarly to Elm/redux there is only one Msg
type for the entire app.
Ideally your message names from different modules wouldn't overlap so the prefix wouldn't be necessary and you'd just group them as you did via comments.
However if this becomes an issue in your case (I didn't run into any, but didn't build very large apps with rid yet) LMK and we can think of a solution.
Keep in mind though that it'd be tricky to introduce another Msg
type as the store update
method assumes exactly one. This also makes sure you handle all possible messages via the match
statement inside update
. Once you have 2 or more Msg
types that becomes much less straight forward, error prone and I imagine in some cases also harder to understand.
Think of update
as a dispatch for all kinds of messages. You could convert it to a per module type there before passing it on, similar to:
fn update(&mut self, req_id: u64, msg: Msg) {
use Msg::*;
match msg {
AddTodo(id) => handleCrud(self, req_id, CrudMsg::Add(id)),
RemoveTodo(id) => handleCrud(self, req_id, CrudMsg::Remove(id)),
[..]
// Non-Crud Messages
}
}
That way you only deal with the entire space of messages in the Msg
type and the update
method, but once you delegate via a narrowed down message type to a handler that part doesn't know anything about Msg
, but in this case only about CrudMsg
.
Thanks for the detailed response! I really appreciate it.
This makes a lot of sense to me. I'm very comfortable with Typescript + React reducers (similar to Redux) and I'm already starting to feel at home here.
My pattern is usually to lean on Typescript to neatly section things off for me and allow me to define everything in separate files:
// ModuleOneReducer.ts
enum ModuleOneActionType {
ActionOne = 'ACTION_ONE',
ActionTwo = 'ACTION_TWO',
ActionThree = 'ACTION_THREE',
}
type ModuleOneAction =
| {
type: ModuleOneActionType.ActionOne;
payload: {};
}
| {
type: ModuleOneActionType.ActionTwo;
payload: {};
}
| {
type: ModuleOneActionType.ActionThree;
payload: {};
};
const ModuleOneReducer = (state: State, action: ModuleOneAction): State => {
// ...
};
// MainReducer.ts
type Action = ModuleOneAction | ModuleTwoAction | ModuleThreeAction;
const Reducer = (state: State, action: Action): State => {
switch (action.type) {
case ModuleOneActionType.ActionOne:
case ModuleOneActionType.ActionTwo:
case ModuleOneActionType.ActionThree: {
ModuleOneReducer(state, action);
break;
}
// ...
}
};
My original thought was that it would be nice to be able to construct a msg
enum like this:
// module_one_model.rs
pub enum ModuleOneMsg {
MessageOne,
MessageTwo,
MessageThree,
}
// store.rs
pub enum Msg {
ModuleOne(ModuleOneMsg),
ModuleTwo(ModuleTwoMsg),
ModuleThree(ModuleThreeMsg),
// ...
}
But I need a single update
where I'm going to enumerate everything anyway, so I'm not sure that would add a lot of value.
Hi! I've got some questions about
Message
andReply
, and best practices for creating messages.Let's say I have an app with a
Message
enum like so:Now, let's say I want to add a new module to my app with a whole new set of messages. I could see myself doing something like:
Is this considered correct, or is there possibly a way to split this up?