justinwoo / purescript-jolly-pong

a library for duct-taping existing redux code into purescript. see README before considering usage.
MIT License
2 stars 0 forks source link

A more sane approach #1

Closed rjregenold closed 6 years ago

rjregenold commented 6 years ago

This is probably not the best place to ask this, but in your project README you say this:

This library is only meant to be used if you are stuck with having to integrate with an existing Redux project and you are on your way to migrating your application to a more sane approach.

I am interested in creating a more complex frontend application using Purescript (so far I've only written a basic snake clone) and am not really sure where to look to handle application state management. I have used Purescript Halogen and really enjoy it. I was looking for a Purescript Redux clone and came across your project. Seeing that warning in your README now has me thinking I am on the wrong path.

Do you mind pointing me in the direction you would go if you were going to create a new Halogen project and needed state management (user auth, several entities with various relationships between these entities, etc)?

Thank you very much!

chexxor commented 6 years ago

I think there's multiple ways to solve the problem. I don't know a "best way" - I've only used that elm architecture (TEA), which doesn't work too great for more complicated apps. My comment is unrelated to this library, btw, but your question seems unrelated, so we are a good match. ❤️

Here's the two big ways of managing state that I see.

Self-managed state

The term "component" in browser apps usually refers to a UI and state bundle. After using TEA for a complicated app, I tend to think that "components", those that manage their own state, disallowing direct/simple contact to it from outside the component, would really simplify solving certain problems. This type of component can be implemented in FP world.

1) The state machine idea. I think this is where Halogen sits. 2) I'm not sure, but the data structures prefixed with "ST" seem related to this problem. 3) Any others? Perhaps that CycleJS architecture?

Externally-managed state

Sometimes multiple parts of your UI, let's call them "widgets" here for lack of better term, need to surface different views onto the same data set. I think the most simple way to solve this problem is to have the state sit outside both widgets, then have the two widgets "query" the data source. This is very much like an HTTP server querying an SQL database as part of rendering the HTML response.

Two scenarios to consider in widgets which query:

1) People who use browser apps like to have interactive controls on their widgets, which means the widget simple re-queries the data source with the modified filters and updates the DOM with the new data. 2) People like their widgets to self-update when the data in the data source changes. This can be solved by the widget occasionally polling the data source, which might be the only option for a data source which sits on a different server of the network, rather than in the browser. Because this can be relatively wasteful, when the data changes less often than a poll, the kids now like to use signals/behaviors/data source-triggered events to tell the widget when the data changed. That can be added into this externally-managed state system, but I wouldn't say it's necessary - IMO, I'd want a data source to have a simple query to use for initial data fetching, and also have subscription for updated data events as an option.

I think number 2 is what people use the redux-style stores for. Either simply as a place to share data amongst several widgets on the page, or as a cache of a remote store. In both of these situations I'd like the redux data store to support simple query-once semantics with optional subscription for updates. Other people prefer to simplify/generalize and say that a query always returns the initial value and updated values, and call it a signal/stream, but I'm not ready to put all my eggs in that basket yet. :)

chexxor commented 6 years ago

My response didn't exactly answer your question, sorry. It looked like an opportunity for me to write down some nice thinking I've been having, so I took it.

It depends what you want that shared, external data store to be.

justinwoo commented 6 years ago

I don't have the best answers really, but a few ideas I'd ask around about on FP Slack:

1) Using hoist to provide your own Free structure

2) Like Alex's suggestion, you could even use the above or wrap it from one layer up and communicate with Halogen's driver API to receive and push messages. One way you might consider with this would be perhaps pairing this with purescript-behaviors like in this demo. For a more controlled version of this using a Cycle.js-like architecture, you might use my Choco-Pie library.

3) Full blown (co)Free Redux via Redox.

These all will have much more learning curve than continuing to just use Halogen, and to be honest, I mostly keep everything in Halogen atm anyway. I think you want to talk to more people in #purescript on FP Slack to see what more experienced users think would be a good approach.

All I can guarantee is that This Library Will Give You Terrible Broken Code, and if you reaaaaally need this library to work with an existing library at any point, please get in touch so you can help maintain this and better understand the crap in this library :smile_cat:

rjregenold commented 6 years ago

@chexxor That is a great and detailed answer. Thank you!

Self-managed state is exactly what I was thinking initially, but I wasn't sure how reusable or maintainable my components would end up being. I was also having a difficult time wrapping my mind around not having a single source of truth (ie: if I need a user object in three different places in my application, should I push the state all the way to the top level component?)

Externally-managed state is the approach that I was thinking about going towards as it seemed to make more sense to me. The idea of having all my state and then my view components just do the rendering is appealing. The state system you described that exposes querying an initial state and optionally subscribing to update events sounds just like what I would want. I might go down the path of attempting to implement something along those lines.

Thank you also for your follow-up answer. I will dig into each of these more. You have been extremely helpful, thank you!

rjregenold commented 6 years ago

@justinwoo Thank you for your reply! I will look into each of these and give them a shot. This thread has been really helpful in giving me some ideas on where to begin.