Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposal] Reactive Components #264

Open
scottbot95 opened this issue Jul 10, 2022 · 0 comments
Open

[Proposal] Reactive Components #264

scottbot95 opened this issue Jul 10, 2022 · 0 comments

Comments

@scottbot95
Copy link

Overview

Add "functional"/"reactive" components similar to React using something like Hooks for state management as an alternative to using Elmish.

Problem

Elmish is a very system for state management. However it comes with some costs, namely a large amount of boilerplate and significant complexity for deeply nested apps. The later is potentially solved by Nested Program Components (#236), however it looks like that feature never got implemented.

Proposed Solution

Defining components:

Users could define components simply as a function of shape IReactiveComponentContext -> Node ie:

let counter ctx =
   let count, setCount = ctx.useState(0).WithSetter()
   ctx.useEffect(fun _ -> printfn "Counter instantiated!")
   div {
      text $"Count: {count}"
      button {
         on.click (fun _ -> setCount (count + 1))
         "Increment"
      }
   }

Instantiating Components:

Reactive components would then be instantiated by a new rcomp function (similar to comp/ecomp).

Hooks:

  • useState<'T>(initialValue: 'T): ReactiveValue<'T>: Essentially the same as the useState hook from React. The ReactiveValue<'T> type contains the current value for that state object as well as a Set function to update state and trigger a re-render. Additionally ReactiveValue is an IObservable so arbitrary change listeners can be attached. A WithSetter() helper extension can be used to provide a similar experience to React (at the loss of the IObservable object).
  • useEffect(effect: unit -> unit, ?triggers: EffectTrigger list): Again very similar to useEffect from React. Essentially it allows users to provide a callback to be called under certain conditions. Valid triggers are AfterInit, AfterRender, and AfterChange of IObservable

Proof-of-Concept:

I have a proof-of-concept created at https://github.com/scottbot95/Bolero/tree/reactive. Happy to submit a PR if that will aid discussion.

Internally it works by creating a new ReactiveComponent class that inherits Component that manages state through a ReactiveComponentContext object and will call the provided render function with the context object on each Render() call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant