Closed JordanMarr closed 4 years ago
You can do something like this:
module App
open Feliz
let counter = React.functionComponent(fun () ->
let (count, setCount) = React.useState(0)
Html.div [
Html.h1 count
Html.button [
prop.text "Increment"
prop.onClick (fun _ -> setCount(count + 1))
]
])
open Browser.Dom
ReactDOM.render(counter, document.getElementById "root")
You could build an entire application without Elmish, probably using something like context where needed.
I think you'll find that once the application grows to a certain side you'll need something like Elmish to help you manage your state. Similar to how in the React world many people start without Redux, but in the end any sufficiently sized application is going to need the functionality that a library like that provides.
Hello Jordan,
I am happy to hear that you are enjoying Feliz so far :heart:
As for your question, I think @Shmew answered it best. Using Feliz, you should be able to write a standalone React application without Elmish. The reason I am using Elmish in the template is because I think the library still is pretty awesome for state management but it is really up to you in how you want to mix and match the approaches with state management.
I believe that Elmish falls short when you have to encapsulate every little detail (for example whether an accordion is open/closed) in the "global" state which is where React components come into play by making small stateful components without polluting the global state that is managed by Elmish.
These "small stateful components" can even be entire pages written with React.elmishComponent
but that too has it's drawbacks, for example in how the component decides to re-initialize it's state when the input props change. Currently is it using reference equality (causes a little problem with HMR when you only change some Html and the component decides to re-initialize it's state again) but maybe I should delegate that choice to the user so there are still some stuff I need to figure out with this library and what it's limitations are.
Thank you both for the guidance.
What would be the difference between using a React.elmishComponent
vs a React.functionComponent
+ React.useReducer
?
React.useReducer
does not use/run side-effects and requires the reduce function "update" to be of type State' -> Msg' -> State'
where as React.elmishComponent
takes an update function of the signature State' -> Msg' -> State' * Cmd<Msg'>
and executes the commands/side-effects once returned by the update
function or but init
.
I tried to write React.elmishComponent
in terms of a variant of React.useReducer
+ custom hooks but couldn't do it at that time: there were a couple of problems with scheduling command execution where commands were executed too many times or weren't executed at all, so I went and wrote an old style React component with a class and internal state to build React.elmishComponent
I can see how it does make sense to store Elmish global state in App and then use the Feliz.Router to send any global state and update functions to the various function component pages like your hybrid example. This seems like an ideal approach, and your hybrid example really brings it to life.
I'm now in the process of porting over one of my current React projects. This will be my first Fable project! So excited!
As an aside, I can imagine this hybrid elmish/stateful component approach being equally useful in the other Elmish frameworks.
I just found Feliz yesterday, and it has me very excited! I love the API, I like that the React Hooks function signatures look closer to the originals, and the documentation is some of the best I've seen!
I've been doing projects with F# back-end and React/TypeScript front-end for awhile now. I love React functional components + Hooks API. The only reason I have hesitated on using Fable is because I think the Elmish pattern would be too many degrees of change for my C# teammates. I wasn't even aware that you could use Fable without Elmish until earlier this week because all the demos I had seen previously focused on Elmish. IMO, it looks overly complex when multiple pages are introduced to Elmish (too much boilerplate code). That's why Feliz - with its emphasis on React.functionComponents and the React.elmishComponent - looks so amazing to me!
Now onto my question: Currently your Feliz template
Main.fs
callsmkProgram
with the Elmish App.fs. I would like to create a sample app to show my team where App.fs consists of aReact.functionComponent
instead (because I think that a strongly typed React would be an easier sales pitch than F# plus Elmish).So then what would be the best way to bootstrap a Function component in this way? I'm assuming that I wouldn't use
mkProgram
, since that's for Elmish (although I suppose I could if I just passed in stubs for the init and update functions). I think I saw aReact.render
somewhere.. would I use that instead?Finally, would there be any drawbacks to this approach? (for example, I see a lot of
Program.with
... functions that I would not be able to use). I like the idea of being about start an app usingReact.functionComponent
s and then be able to choose to branch out to useReact.elmishComponent
s only when I want.