Hello friend, it's been a while I bothered you with some retarded question, so it's time for another take. 😂
Can you please somehow describe what is the difference between Feliz.ElmishComponents
and Feliz.UseElmish
? I see them both are React component having Elmish MVU parts. Are there any typical scenarios where you would choose one instead of another? I love easy of use of Feliz.UseElmish
and just fear I am maybe missing something even cooler here. 😄
So Feliz.ElmishComponents
isn't very useful anymore, and predates Feliz.UseElmish
. The reason for this is that originally Feliz.ElmishComponents
was a class based component, which I rewrote as a function component. A bit after that, we realized that if it's a function component it's trivial to just convert it into a hook. That is how Feliz.UseElmish
came to be. So now Feliz.ElmishComponents
is really just a function component that calls the hook. In fact, if you look at the project for Feliz.ElmishComponents
you'll see it's tiny now.
Thanks a lot, Cody!!! So if I get i correctly, Feliz.UseElmish
is the default one, right now.
Yeah, we mostly still have Feliz.ElmishComponents
around to not break people. You can consider it to be deprecated.
Perfect! Thanks again!
If it is "deprecated" it could be a good idea to mark it "Obselete" and redirect people to the recommended API.
What do you think?
Yes, we are just discussing with colleagues from F# team that we should do PR to documentation (maybe with link to this issue)
Ok, I did it here - https://github.com/Zaid-Ajaj/Feliz/pull/264
Are there any typical scenarios where you would choose one instead of another? I love easy of use of Feliz.UseElmish and just fear I am maybe missing something even cooler here. 😄
Hi Roman, good question!
The difference like Cody mentioned is that Feliz.UseElmish
is written with hooks as opposed to a full component implementation of Feliz.ElmishComponents
.
However, that is not the entire story, because Feliz.UseElmish
also follows _hook semantics_ when it comes to component re-initialization by the use of the dependency array as the last argument which is a big difference from Feliz.ElmishComponents
that doesn't do that where reinitialization was hacky: making up unique component keys from the input, yikes!
Feliz.UseElmish
can also be combined with other hooks like subscriptions in the same component.
What do I mean by "re-initialization"? Well, imagine you are loading the user profile component based on URL changes as follows:
#/user=profile/{userId} -> UserProfile { UserId = userId }
Basically, we want to re-initialize the UserProfile
component (calling init
to reset the state) when the input UserId
changes:
type UserProfileProps = { UserId : int }
let UserProfile = React.functionComponent("UserProfile", fun (props: UserProfileProps) ->
let state, dispatch = React.useElmish(init props.UserId, update, [| props.UserId |])
Html.h1 (sprintf "UserProfile(UserId=%d)" props.UserId)
)
// later on application entry:
React.router [
router.onUrlChange (parseUrl >> UrlChanged >> dispatch)
router.children [
match state.CurrentUrl with
| [ "user-profile"; Route.Int userId ] -> UserProfile { UserId = userId }
| _ -> Html.h1 "Not found"
]
]
Because we providing the the dependency array [| props.UserId |]
to the hook (third argument to the hook), the component will automatically refresh and call init
again to reset the Elmish dispatch loop. This is what we want because init
was a function of the input props.UserId
so we want to call it again when the props of the components changes.
When neither the init
nor the update
function require additional input from the props of the component, you simply provide an empty dependency array:
let state, dispatch = React.useElmish(init, update, [| |])
This is typically used for components that don't need input from outside, like the entry component of the application.
It can be a bit tricky to get used to the dependency array but they make a lot of sense, read more about it in Conditionally firing an effect from the hook docs.
Final tip: Feliz.UseElmish
is really powerful because it gives you a full-fledged Elmish dispatch loop the same way you are used to with traditional Elmish apps. However, setting up types for the state and messages can be a bit too much when your components are simple. Do you need a couple of state flags? Then a couple of state variables with React.useState
might be enough. Do you need to fetch and render some data without further interaction? Then React.useDeferred
might do the trick. I will go for Feliz.UseElmish for complicated pages which have many events and lots of use interaction.
Wow, typical Zaid's response. 😄 You should start teaching those things, man! I can finally understand. Thanks again! ❤️
Most helpful comment
Hi Roman, good question!
The difference like Cody mentioned is that
Feliz.UseElmish
is written with hooks as opposed to a full component implementation ofFeliz.ElmishComponents
.However, that is not the entire story, because
Feliz.UseElmish
also follows _hook semantics_ when it comes to component re-initialization by the use of the dependency array as the last argument which is a big difference fromFeliz.ElmishComponents
that doesn't do that where reinitialization was hacky: making up unique component keys from the input, yikes!Feliz.UseElmish
can also be combined with other hooks like subscriptions in the same component.What do I mean by "re-initialization"? Well, imagine you are loading the user profile component based on URL changes as follows:
Basically, we want to re-initialize the
UserProfile
component (callinginit
to reset the state) when the inputUserId
changes:Because we providing the the dependency array
[| props.UserId |]
to the hook (third argument to the hook), the component will automatically refresh and callinit
again to reset the Elmish dispatch loop. This is what we want becauseinit
was a function of the inputprops.UserId
so we want to call it again when the props of the components changes.When neither the
init
nor theupdate
function require additional input from the props of the component, you simply provide an empty dependency array:This is typically used for components that don't need input from outside, like the entry component of the application.
It can be a bit tricky to get used to the dependency array but they make a lot of sense, read more about it in Conditionally firing an effect from the hook docs.
Final tip:
Feliz.UseElmish
is really powerful because it gives you a full-fledged Elmish dispatch loop the same way you are used to with traditional Elmish apps. However, setting up types for the state and messages can be a bit too much when your components are simple. Do you need a couple of state flags? Then a couple of state variables withReact.useState
might be enough. Do you need to fetch and render some data without further interaction? ThenReact.useDeferred
might do the trick. I will go for Feliz.UseElmish for complicated pages which have many events and lots of use interaction.