Controller. You need a controller. Or a smart model, in this simple case.
That’s what react/redux has done to you, selling this ‘immutable functional’ flavoured thing. While it is immutable at the programming surface, it is actually a series of complex updates with little to no help from the ‘store’ for convenient access. In pure js, when you want project.tasks, you just:
class Project {
get tasks() {
return db.tasks.filter(x => x.project_id == this.id && !x.deleted)
}
}
class Task {
get project() {
return db.projects.find(x => x.id == this.project_id)
}
del() {this.deleted=true}
}
db.tasks = [].map(Task)
db.projects = [].map(Project)
... in a view:
h(button, {bind:[cr, 'add_task']}, '+')
cr.project.tasks.map(task =>
...
h(check, {bind:[task, 'done']})
h(button, {bind:[task, 'del']}, 'x')
... in a controller:
add_task(project) {
db.tasks.push(new Task({project}))
}
In “immutable functional state transformer based on async-dispatched store”, which these re-whatever buzzwords are, you cannot have neither smart data items, nor a good controller that could join unrelated objects together, nor recombinable data sources, nor nice testable api boundaries. And when someone whispers MVC, you think about web 1.0 patterns, with it’s “MC in MVC is backend roundtrip” meaning.
This particular example is a set of five dead-simple classes (DB, Project, Task, TaskListController and TaskListView), almost all orthogonal and useful/testable on their own. Easy for imperative thinking and managing^, cause UI is suddenly imperative. You constantly battle with immutability, lack of control, state copy-transfer and tons of boilerplate for a simple action, can’t you see? You’re doing a monad bind operation by hand, because there is no do-notation in your language, and where there is, it exists and is called “do” for a reason. How did they miss that completely? /rant
^ e.g. want to see deleted tasks? Write a getter in a controller or a db (depending on locality requirements) and use it in a view as if it was a pojo array. Reimplement on demand to leave your tests and logic intact.