Closed itrelease closed 7 years ago
Do you have a more complex example where you're actually updating the model before firing off the effect? It would be helpful to illustrate some benefits.
I'm not a big fan of that aspect of Elm, to be honest. It creates a lot of that Cmd.none
boilerplate, like in your example (or the shorthand version with !
). I'm sure elm had a very good reason to do it that way (whether it be a type system requirement or effect management reason). elm is a fantastic language, but understanding how to chain updates & effects isn't very simple.
With javascript's flexility I'm liking how hyperapp just lets you call the reducers and effects the same way.
@SkaterDad often when I need to request something I need to set loading
flag or reset some field to initial state
The example in the readme implies that's already possible, since you can call the update functions from within the effect?
const effects = {
waitThenAdd: (model, msg) => {
msg.toggle()
wait(1000).then(msg.add).then(msg.toggle)
}
}
EDIT: I hope to start migrating an app sometime this week, and definitely plan on doing things like that also. Hopefully it goes smoothly.
@SkaterDad I didn't said that you can't do this in current implementation I just pointed that you have to call this side-effect things directly and call update methods inside these effects
which I think looks not that good in contrast with elm
Fair enough :smile:
This is the fun part of open source to me, learning the different ways people prefer to do things.
@itrelease 🤔 What would be the proposed syntax using JavaScript?
@jbucaran
update: {
loadMore: (model, data, effects) {
return {
model: { ...model, loading: true },
effect: effects.fetchMore(data.url) // but this shouldn't start fetching immediately this should be more like Task thing that will be forked and run by runtime
};
}
@itrelease Hmm, this is getting interesting!
I'll need a more concrete example, if possible, based in one of the existing ones of how both models would contrast.
There's an example in the documentation for effects.
How would that entire example look in your model?
If it isn't reproducible, then you can come up with a new example yourself, but please make sure to show both an implementation using HyperApp and one in pseudo-code in your model/idea.
@jbucaran
const model = {
counter: 0,
waiting: false,
error: null
}
const view = (model, msg) => {
return html`
<button
onclick=${msg.waitThenAdd}
disabled=${model.waiting}
>
${model.counter}
</button>
`;
};
const update = {
waitThenAdd: (model, data, effects) => {
return {
model: ({ ...model, waiting: true }),
effect: effects.wait(
1000,
(_) => ({ ...model, waiting: false, error: null, counter: model.counter + 1 }),
(err) => ({ ...model, waiting: false, error: err })
)
};
}
};
const effects = {
wait: (time, onReject, onResolve) =>
(model) => new Promise(resolve => setTimeout(_ => resolve(), time));
}
app({ model, view, update, effects });
@itrelease Thank you for your time and writing this for me. I'm going through it now, trying to understand what's going on.
At first glance I can say, however, it looks more complex than the original example.
I agree that the example now seems a bit more complex. Maybe all we need to do is state in the docs that the effects
do not cause a re-render to occur. Essentially, that is the only difference currently between effects
and reducers
.
What is TEA? The drink? :laughing: Sry, i'm not Elm.
As seeing the examples and discussion, what's the problem to do such thing currently?
What about the following?
const model = {
counter: 0,
waiting: false,
error: null
}
const view = (model, msg) => {
return html`
<button
onclick=${msg.waitThenAdd}
disabled=${model.waiting}
>
${model.counter}
</button>
`;
};
const update = {
add: (model, data) => (data)
};
const wait = (time) => new Promise(resolve => setTimeout(_ => resolve(), time))
const effects = {
wait: (model, msg, data) => {
msg.add({ waiting: true })
wait(1000)
.then(() => {
msg.add({ waiting: false, counter: model.counter + 1 })
})
.catch((err) => {
msg.add({ waiting: false, error: err })
})
}
}
app({ model, view, update, effects });
I believe it won't work, but.. believe it is possible to be done too :D Just a matter of thinking.
Oooh, right TEA means ... okey :D
Going to close here as I don't think I'll be changing the effects API.
Maybe it would be better if
effects
shouldn't be called directly by user but go along with result of updating model as a second element in an array or some other structure and that second element should be handled by runtime so it will be look more like TEA: