purescript-react-redux
purescript-react-redux copied to clipboard
Question: dispatch signature
Hi,
I'm having troubles figuring out why exactly the type of dispatch is polymorphic over f
: f action -> f action
. Does it has anything with middleware? If so, how could I put it to greater use? Async actions?
Currently in my code I've got couple of invocations like void $ dispatch $ pure $ Login $ Login.AttemptLogin $ LoginData { username: mail, password }
and f
is mostly inferred to be (redux :: REDUX | eff)
for all eff.
When I started working on this, I was experimenting a bit and giving some flexibility in the types since I wasn't precisely sure how I would ultimately end up using this representation. I agree that f
is mostly going to be Eff
, but I suppose the intention is to have f
free to be other MonadEff
instances in case the user requires the ability to dispatch an action in a monad besides Eff
. An example you mentioned could be when using Aff
.
OK, but how about the fact it's not merely an f Action
, it is a f Action -> f Action
?
Let's discuss with example:
render dispatch this = do
props <- React.getProps this
pure $ loginView { onClick: \({ mail, password }) -> do
log "test"
void $ dispatch $ pure $ Login $ Login.AttemptLogin $ LoginData { username: mail, password }
, enabled: not props.inProgress && isNothing props.authData }
Here, f
becomes:
Eff
( "props" :: ReactProps
, "refs" :: ReactRefs (() :: # Effect)
, "state" :: ReactState
( "read" :: Read
)
, "console" :: CONSOLE
, "props" :: ReactProps
, "refs" :: ReactRefs
( "read" :: Read
)
, "state" :: ReactState
( "read" :: Read
, "write" :: Write
)
| t0
)
Now, the type of the render is:
type Render props state eff f action = (f action -> f action) -> React.Render props state eff
this means, our dispatch now works within the Eff
that's provided by the onClick
handler. So far so good, but now I'm feeding it with pure $ Login ....
and that probably always is going to be pure
, because if I want any effects I can do this in the onClick
handler.
Therefore, I think the signature Action -> f Action
could be more appropriate. But then I'm not sure why we need to return an Action
at all (vanilla redux seems to be doing this, I'm not sure what for, is it only for convenience? Does dispatch
always return an action, or can it return something else depending on middleware?)
Alternatively, I guess it would be g Action -> f Action
, meaning it should be some effect that would be executed in a context of a store (again, middleware?), but then I'm not sure what could it potentially be.
// EDIT: hmm, maybe current signature makes it more convenient should one employ action creators - it would mean they could be effectful too...
Thanks for the example. I don't really have a strong argument for f Action -> f Action
or Action -> Action
. I suppose the original idea was to keep things flexible for how actions are obtained. I admit that I have only really been doing void (dispatch (pure action)))
.
Maybe adding a function createClassEff
could be useful where f
would be Eff eff
?
On the note of returning the action from the dispatch call, I just followed what redux does in this case. Again, I don't have a strong argument for this either way.
I suppose I'm gonna leave it as it's now and just wait to gather more use cases.
I think I'd like to reopen this.
I want to explore an idea for how to better utilize the f
type.
I will post my thoughts here once I work them out a bit more.