Coder Social home page Coder Social logo

dbrattli / fable.reaction Goto Github PK

View Code? Open in Web Editor NEW
142.0 12.0 19.0 6.89 MB

Fable Reaction - Reactive (AsyncRx) for F# Elmish and Fable

Home Page: http://fablereaction.rtfd.io/

License: MIT License

F# 100.00%
reactive elmish fable fsharp reactivex elm web-framework

fable.reaction's Introduction

Hi there ๐Ÿ‘‹

  • ๐Ÿ”ญ Iโ€™m currently working on Fable Python and RxPY
  • ๐ŸŒฑ Iโ€™m currently learning Kafka and Dapr ...
  • ๐Ÿ‘ฏ Iโ€™m looking to collaborate on Fable Python
  • ๐Ÿค” Iโ€™m looking for help with Fable Python
  • ๐Ÿ’ฌ Ask me about working for Cognite
  • ๐Ÿ“ซ How to reach me: https://twitter.com/dbrattli
  • โšก Fun fact: I have cycled 2000 km from Windhoek (NA) to Cape Town (ZA) ... twice.

fable.reaction's People

Contributors

dbrattli avatar dependabot[bot] avatar fradav avatar johannesegger avatar juselius avatar naartjie avatar rommsen avatar scullman avatar sergey-tihon avatar spingee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fable.reaction's Issues

Need simpler example for Elmish.Streams.AspNetCore.Middleware

The Magic example is very nice, but I am having difficulties figuring out how it works outside of all the particulars of the app.

It would be very good to see a very basic Counter example using:
Saturn + Elmish.Bridge + Elmish.Streams.AspNetCore.Middleware

If not Saturn, at least Giraffe + Elmish.Bridge + Elmish.Streams.AspNetCore.Middleware

Parameterize the query based on the current state

It would be really nice if we could change the query based on the current state. Thus instead of having:

query: IAsyncObservable<'msg> -> IAsyncObservable<'msg>

it should be something like:

query: 'model -> IAsyncObservable<'msg> -> IAsyncObservable<'msg>

This also means that the query function needs to be called whenever the model changes and not be a single-shot as today.

Documentation update

Hi, according to docs one should use Reaction.StreamView, but I can't find any in source code - can you update documentation how one can use this library with elmish?

Using with Elmish.WPF

First off, this looks like a very nice project, complete with documentation and examples!

For my question, I would like to incorporate the use of Rx observables in an Elmish.WPF app. Can I achieve this by using Elmish.Reaction? Also, are you going to put Elmish.Reaction on NuGet?

Autocomplete example not working on Edge browser

Running the example for autocomplete doesn't work for Edge browser.
Specifically, no call is dispatched when typing in the client app pauses, same client accessed from Firefox Dev edition works fine.

Client and server executed using fake build --target run

Websocket message channel filtering

Is there a way avoid having all messages over the websocket? I'd like to just have a subset of the messages passed over the websocket with the rest being just handled client side.
Thanks

How to have query map a message for the current connection once and send the mapped message all connections

I'm trying to do something similar to the websocket example.

When using the query with websockets, when there multiple connections, is it possible to have a single connection submit a message, have the query map (handle) that message once and include all connections in the response?

This may be easier to explain with a concrete example.
I have a list of orders and multiple users (connections) selecting orders from the list. I would like the server to keep track of which orders are currently selected by each user. When a user A selects order 123, the server receives a message requesting order 123 be assigned to user A, the server assigns order 123 to user A (updates its local state), and sends a notification to ALL users (connections) that order 123 is selected by (assigned to) user A.

I understand how to determine if the message being processed is for the current connection. However, I don't see a way to transform that message just once for all connections. Am I missing something obvious, or perhaps trying to do something this library isn't intended for?
Thanks

Fix Introduction in getting started

To use Fable Reaction with Elmish you need to call the Program.withStream with your reactive query. The query function takes an IAsyncObservable<'msg> and returns a possibibly transformed IAsyncObservable<'msg>.

This doesn't fit to the following code example in Getting Started

Dispose subscription when observable terminates

Currently a subscription to an observable is only disposed when the subscriber disposes it. If I remember correctly Rx.Net additionally disposes a subscription when the observable terminates (successfully or with an error).

Given the following code:

let o = AsyncRx.take 5 fileChangedObservable // implemented using `FileSystemWatcher`
let! sub = o.SubscribeAsync onFileChanged

The resources used for the FileSystemWatcher are not released until someone calls sub.DisposeAsync () - even if all of the 5 events have been triggered.

I don't see an easy way to do this because there are so many places where anonymous objects that implement IAsyncObservable are created and I don't see an easy way to add the disposal of the subscription to all of them.
In the best case it's not even possible any more to create an IAsyncObservable that doesn't dispose the subscription on termination.
What do you think?

Make a reusable component of the Autocomplete example

Make a reusable component of the Autocomplete example so it may be easily included re-used on pages within an application. Bundle it as Fable.Reaction.AutoComplete.

What does a component look like?

type IReactionComponent<'model, 'view, 'msg, 'key> =
    abstract member update: 'model -> ('msg -> unit) -> 'model
    abstract member view:  'model -> Dispatch<'msg> -> 'view
    abstract member query: ('model -> IAsyncObservable<'msg> -> IAsyncObservable<'msg>*'key) -> Elmish.Program<_,_,_,_>

Support disposing AsyncDisposable multiple times

AsyncDisposable.DisposeAsync should be idempotent, so disposing something multiple times should be the same as disposing it just once. AsyncDisposable.DisposeAsync can't tell if cancel itself is idempotent, so it should only call it once. I think this could be done with the following implementation:

type AsyncDisposable (cancel) =
    let mutable isDisposed = 0
    interface IAsyncRxDisposable with
        member this.DisposeAsync () =
#if FABLE_COMPILER
            if isDisposed = 0 then
                isDisposed <- 1
                cancel ()
#else
            if System.Threading.Interlocked.CompareExchange(&isDisposed, 1, 0) = 0 then
                cancel ()
#endif
            else
                Async.empty

I was about to create a PR with this change (and also used AsyncDisposable.Create everywhere instead of anonymous objects that implement IAsyncRxDisposable) but it wasn't easy to separate Core.fs and AsyncDisposable.fs because they depended on each other. And again if it's possible that library users can't create anonymous objects that don't follow this rule I would very much prefer that.
What do you say in general? Do you think it's worth to implement?

Why Async.Start' ?

I am seeing this code:

static member Start' (computation:Async<unit>, ?cancellationToken: CancellationToken) : unit =
            #if FABLE_COMPILER
                Async.StartImmediate (computation, ?cancellationToken=cancellationToken)
            #else
                Async.Start (computation, ?cancellationToken=cancellationToken)
            #endif

But in fable Start and StartImmediate are the same thing.

Showcase page

Great project with a nice README and a samples! ๐Ÿ‘ ๐Ÿ‘ Would it be possible to add a simple web using GH pages with the live samples (as in the GIFs you tweet)? That would be very helpful for users to get a quick grasp of Fable.Reaction benefits.

Also, please don't forget to add a link to your project in awesome-fable so it's easier for other people to find it :)

Discuss: Changing the name query to something different

For me (thinking in terms of CQS or CQRS) a query is something that is not changing data. It might even be idempotent. But here we are actually performing side requests and explicitely replacing (Elmish) Commands. So when working with Reaction, query always goes against my intuition.

I am not sure about better names but when I showed Elmish.Reaction to my peers I have always talked about streams and never about queries.

What was the original idea, behind "query" and do you think that we could find a different name for it?

A more realistic sample is needed

I try to play with this library, but I did not know how to deal with multiple pages or components.
Like in the AutoComplete sample, how can I compose the AutoComplete component with other component? How to compose those query elegantly?
Thanks!

Messages based on Commands are not fed into stream

Hey Dag,

I am trying to use Elmish Stream in the Safe Confplanner and I am banging my head for the last couple of hours because it is not working as (I) expected.

In the Confplanner I need to work with commands (so no mksimple) and I have a couple of situations where I need to create messages from commands within the update function. For this I am using the elmish Cmd.OfFunc.result MyMsg et al functions. It seems that those message are never fed into the message stream (it is somehow circumvented and the messages go directly into update). Is this expected behaviour? I can create a minimal repro but I wanted check first if this is the way it is supposed to be.

Stream handling function does not obtain the actual state (it is always the initial one instead)

While building an app via this library stumbled upon a problem that I can't completely understand. Should the stream handling function be designed assuming the input model/state parameter is the actual/current state or the initial one? As I understand this code, it should get the updated state. But in my app the stream's state parameter always retains the initial value.

Example

The example is simplistic and meaningless -- it is just for demo purpose.

Brief explanation

The state contains SavedInput : string option, that is taken from HTML Input element after clicking "Save" button.

The messages are SaveNewInput of string , UpperCase and LowerCase. The 1st one is simply propagated from the stream, the last two are ignored if SavedInput is None:

messages
|> AsyncRx.choose (function
    | SaveNewInput _ as msg -> Some msg
    | UpperCase
    | LowerCase as msg ->
        state.SavedInput
        |> Option.map (fun _ -> msg)

The intent is to ignore the messages UpperCase and LowerCase until user saves an entered string. So if the stream function obtained the actual state, the example would work properly. However in reality it always ignores UpperCase and LowerCase messages, because the stream function never gets an updated state -- it always has the initial value.

So this is the problem I want to clarify.

Fable.Reaction on other elmish platforms

Is it possible to make this thing work with nonweb elmish applications ? If I want to use this approach on Fabolous or other elmish platforms, how can I get started?

Feliz update breaks Magic example

With the Fable.React update (see my PR) the magic example is broken.
There was some api changes in Feliz.Bulma (easily fixed) but now the value from server is fetched again and again. Something related to FunctionComponent changes in Fable.React ?

Updating to Fable.Core 3.0 and friends

Hi, any plans on updating to latest versions of Fable.Core etc? I'd like to make the update for SAFE template, currently Fable.Reaction seems to be the only dependency we have that doesn't come with Fable.Core >3 support.
I'm happy to help with that if necessary

AutoComplete example doesn't receive Msg.KeyboardEvent

I've tried extending the AutoComplete example, and hit an issue where messages dispatched from the view function never make it to the update function.

For the example as it stands, this doesn't matter, since it ignores everything but Msg.Loading and Msg.QueryResult.

However, it indicates that the dispatch function being supplied to view doesn't do what it's supposed to do.

(For what it's worth, I'm trying to add Msg.ClickedSelection to model the fact that a user made a selection and then hide the menu in the next update)

How to extend existing Elmish apps

My current, already existing Elmish project would benefit from an Autocomplete feature.
I added the dependency for Reaction, added
Program.withMsgStream App.stream "msgs"
Well, and already here I am lost.
I thought I can just filter / choose the right events and pass it down to the right sub component.

let stream model msgs =
    let asSubCompMsg msg =
        match msg with
        | SubCompMsg msg -> Some msg
        | _ -> None

    match model with
    | Loaded model -> SubComponent.State.stream model.SubComponent (AsyncRx.choose asSubCompMsg msgs)
    | _ -> Stream.none

...and so on, similar how sub components are initialized/updated in Elmish.

To my first surprise, my app stopped working, as no messages were passed anymore. I just did not expect that the stream acts as a filter.

At that point of time I just wanted to get the app running again.
So i changed my stream method to
```let stream model msgs = AsyncRx.toStream "msgs" msgs````
I expected that now all messages will remain unchanged as before. But no, it still did not process msgs anymore.

If I comment Program.withMsgStream, the app works again (beside autocomplete, of course).
I guess I am missing something obvious.

Usage with older Fable compiler

Hi,
I tried to add Autocomplete example to my app which was based on safe stack template, it didnt work because it cant find some compiled js , see the warning from console:

WARNING in ./src/Client/Views/Autocomplete.fs 177:23-81 "export 'Reaction$$$useStatefulStream$$5E046E25' (imported as 'Reaction$0024$0024$0024useStatefulStream$0024$00245E046E25') was not found in '../../../.fable/Fable.Reaction.3.5.0/Reaction.fs' @ ./src/Client/Views/Index.fs @ ./src/Client/App.fs @ ./src/Client/Client.fsproj

when i run autocomplete example from this repo it will generate *.js in .fable/Fable.Reaction.3.5.0 but not in my app, there are no js files.
So is this library only usable with fable compiler 3.0 and my only option is upgrade my app to it? Or is there some "workaround".
Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.