Fulma / Fulma

Binding for Elmish using Bulma CSS framework
https://fulma.github.io/Fulma/
Other
186 stars 52 forks source link

Explore converting Fulma.Elmish to using stateful component #101

Open MangelMaxime opened 6 years ago

MangelMaxime commented 6 years ago

When updating the Fulma docs site, I kind of re-discovered the usage of stateful component via Fable.

Using them from Fable, we still gain access to intellisense, compilation checking, etc. Also I would say it's less verbose to write and the output is less verbose too.

From my experience, writing the component in like I initially did for the DatePicker is harder to reason about. Elm is doing it that way because their architecture only provide the support of "stateless" components. But because we use react, we could / should benefit of both worlds.

Because, the Fulma.Elmish components are dedicated to be some kind of "black box" using stateful component could be benefit.

Example of stateful components

@alfonsogarciacaro Any pros / cons ?

@EdouardM I am asking to you too because, I know you wrote one/two components that we will include in the next release :)

alfonsogarciacaro commented 6 years ago

Yes, stateful components are useful to prevent pollution of the global state with tiny things that only affect the UI (like an open box, etc). Just remember you lose debugging, auto-saving, etc, for those things. Also, with latest Fable.React beta you can use tiny Elmish components: they have an API similar to Elmish but translate to React stateful components.

MangelMaxime commented 6 years ago

The component would still be controlled by the caller application via props. We would just use the stateful to manage UI state. I think it should be acceptable if the user experience is better and if it make it easier to maintain.

I will take a look at the "tiny Elmish components" even if I am still not convince by it :)

EdouardM commented 6 years ago

Both are very interesting, it's fun you mention that because I wrote a first version of the sortable table but I wasn't very happy of it because state info like sort or which page we are on don't have to be in the way of the developper who only wants to add the component in a view.

I agree that including this information in global state and having it bubble up from the component to the top with elm message passing is adding some noise.

I am going to explore stateful component possibility.

MangelMaxime commented 6 years ago

If you want to share your work, please send a PR targeting #93

The structure of the docs changed a bit but you should not be lost. And also, will have access to the latest Fulma API and so we will not have to port it.

ghost commented 6 years ago

I do not think that reusing stateful components is such a big problem with Elmish if the component to be reused is in a stable production-ready state. They might be blackboxed for Elmish, but if I do a project for someone I care more for those things being present for business logic, networking and prototyping of the actual application I'm about to write and not so much about how a good working, nice looking component handles its visual state internally.

The bottom line for me would be: Do reuse good stable, stateful React components that really work well with Elmish, but don't bother doing with alpha/beta ones 😄. The leverage you can get from a lot of resources that went into existing JavaScript is huge.

@alfonsogarciacaro I really did not get the tiny Elmish concept from a first look. Could you give an example and clarify how this would look in practice?

MangelMaxime commented 6 years ago

Thanks for your answer @kfrie I still have problems with how react work even if I am using it daily.

Also, in the case of Fulma, we can't really use existing React components because basically there is none having Bulma style + doing the behavior we are expecting from it.

Also, I discover because we use Bulma components, we should also allow users to customize part of the resulting components.

Example:

At work, we are using the DatePicker and we needed to make it bigger via IsLarge I end up using a local version of the component because we don't offer this possibilities by default.

But yes, I agree that in theory we can use either stateless or stateful components with Elmish. We are already doing that for RechartJS or ReactLeaflet for example.

ghost commented 6 years ago

Hmm true that react components are almost always tied to some specific style. I'm quite new to all this and used semantic-ui-react and react-google-charts so far, so I had no problems with style, but charts don't have custom button, dialog etc, so this could get bad with other components visually.

For Fulma.Elmish components it would be really nice to offer some sort of theme per component basis declared once in some mapping. Is something like that possible? The custom theme would be on top of Bulma I assume.


let myAwesomeTheme = {
 // declaring a theme record
}

let themeConfig = [
  typeof<DatePicker>, myAwesomeTheme 
]

...

|> Program.withThemeConfig themeConfig 
ghost commented 6 years ago

Are there any plans to gather a repository of wrapped React components for Fable. Would be really nice if that was offered and maintained at a single point, like DefinitelyTyped for .ts definitions?

MangelMaxime commented 6 years ago

We already have this kind of repository here

ghost commented 6 years ago

Ah I know that one! 😄. Just did not notice it was open for such contributions. So I would create Fable.React.GoogleCharts and Fable.React.SemanticUI und src and give them their own Release Notes and send PR?

ghost commented 6 years ago

I just stumbled across Cycle.js and its programming model. The way components are defined there do not have the problems discussed here! Is something simliar possible with Elmish in any way?

MangelMaxime commented 6 years ago

Elmish is not exclusive to React. It's jut the most common renderer we have.

Pure Elmish is just about a loop to manage a state and handle message. It's only render to react when using Elmish.React package. So yes you can you cycles with Elmish if you write the renderer part for it.

If you have a question about Elmish you probably should ask it on the Elmish repo.

ghost commented 6 years ago

I think cycle.js has its own app lifecycle, so it is more than just a way to reflect virtual DOM. So it is really an alternative programming model. What I think is very special about it, is that Cycle Programs are reusable as components themselves, which is not the case for Elmish:

type Program<'arg, 'model, 'msg, 'view>

Can't use that as part of a larger app as component or can I?

I just came across it and got hooked by the ideas in like 10 minutes. Does anyone of you have working knowledge with Cycle.js and the approach. Would much appreciate some real-world insights.

I placed it here first because it was about components, but I will ask in Elmish repo too.

MangelMaxime commented 6 years ago

All Elmish components are reusable by default. So I am not sure to understand.

Program, is not Elmish component but what we use to register an Elmish application which use Elmish component if we can say.

ghost commented 6 years ago

Here I found a great comparision of those different UI concepts, including Elm Architecture. It is not, that they are not reusable, it is just the way that reuse can become tedious in practice though the repeated nesting. I don't know how to express that otherwise, I'm not a native English speaker after all :). I will try to code something that demonstrates the problem I mean.

I'm just asking those questions to support you to find the best way for building up a set of great Fulma.Elmish components that are of true reusability and can provide value over other existing approaches :).

EdouardM commented 6 years ago

Hello @alfonsogarciacaro,

I am trying to convert an elmish component I built (sortable table) to the Fable.Helpers.React.reactiveCom. I followed this path because I had a fully working set of files with the Elmish architecture in place and the gap to convert it seemed smaller.

However I am facing one issue : I don't have Commands. The update function in the reactiveCom does not return any Command but an updated state.

I am currently trying to stick with the component functions signature and thus I removed the emitted command from the update function to put them somewhere in the view function but I get many React warnings and null errors. I assume then that the view function is not the right place.

Do you have any recommandation on how to transition from Fable.Elmish to reactiveCom without Commands?

Do you have any example of the reactiveCom used in an application ?

Kind regards, Edouard

alfonsogarciacaro commented 6 years ago

Hi @EdouardM! I haven't actually used reactiveCom in an application yet, we designed it together with @zaack mainly to isolate some state from the global state. But it's true it's very convenient to build stand-alone Elmish-ish components too. It shouldn't be difficult to add commands, as it's just a callback that receives a dispatch function, which only has to run update and then call .setState.

Do you want to give it a try and send a PR to fable-react? I can also have a look when I have a moment.

EdouardM commented 6 years ago

Ok @alfonsogarciacaro I am going to give it a try and let you know.

stroborobo commented 5 years ago

Hi! I've started using this date picker today and thought about changing it to issue two messages (value change and ui change) and exposing a few smaller view function (like for the input). But seeing this issue I can also go this way if that's still wanted as it would get rid of the second message already.

So stateful components, tiny Elmish components or the classic way?

Nhowka commented 5 years ago

What about the new hook feature? Can it be a better fit here?

MangelMaxime commented 5 years ago

TBH I didn't give too much thought to this issue in a while 😅.

If you want to stay in a functional approach hooks are indeed a way to make a function stateful.

stroborobo commented 5 years ago

I'll have a look at those :)

stroborobo commented 5 years ago

Hey guys, I'm having a little trouble using function components. Maybe I haven't understood what they are from a Fable point of view. Since most view functions are something like 'foo -> 'bar -> ('msg -> unit) -> ReactElement and a function components appears to be something like 'props -> ReactElement, can we actually use them inside of what I thought of as a typical view function "tree"?

I tried building a function 'props -> ReactElement (props as in an anonymous record that contains all the parameters) and calling Hooks.useState in there, but only got errors that I should call it inside the body of a function component.

This is where I am right now: https://github.com/stroborobo/Fulma/tree/datepicker-react-hook

Nhowka commented 5 years ago

got errors that I should call it inside the body of a function component.

This is where I am right now: https://github.com/stroborobo/Fulma/tree/datepicker-react-hook

Probably that can be fixed using FunctionComponent.Of to let react know that the function is now a function component. Are you using the example?

stroborobo commented 5 years ago

Very good tip, thank you, I missed that. 👍

stroborobo commented 5 years ago

I just removed the renderer from the PR, so it's just the hook now, please have a look: #211