hexops / vecty

Vecty lets you build responsive and dynamic web frontends in Go using WebAssembly, competing with modern web frameworks like React & VueJS.
BSD 3-Clause "New" or "Revised" License
2.82k stars 144 forks source link

formally standardize on Redux pattern + a dispatcher package #73

Open slimsag opened 7 years ago

slimsag commented 7 years ago

The Redux React pattern is IMO the most logical, sane, and extremely simple to understand pattern for store management in applications. I think we could do very good by standardizing on this pattern -- and likewise on a single dispatcher package in the Vecty root -- instead of asking people to decide and write their own dispatcher.

This means that people get a fuller picture from the beginning, and don't need to research "should I use redux or flux?" etc. and try to figure out how it relates to Vecty first. Instead, we present a unified front by adopting Redux patterns formally in documentation etc.

Note that this doesn't really lock us into one or the other -- it just says "unless you have good reason, stick with the redux pattern we recommend" and as a plus makes all Vecty applications pretty easy to reason about in comparison to React apps.

awitherow commented 7 years ago

@slimsag any ideas on this?

slimsag commented 7 years ago

Haven't looked at it.

slimsag commented 7 years ago

On the topic of redux stores.. multiple people have reached out to me about it via Slack which isn't the greatest way to keep track of things, so I'll try to copy down relevant details here now.

@marwan-at-work has reached out to me about his implementation of Redux in Go: https://github.com/marwan-at-work/vstore I have not yet head a chance to look at it at all.

@norunners has also had conversation with me about a redux implementation; and his thoughts on @marwan-at-work's version was that it may not be easy to use or that he doesn't understand its power with the given examples. Again, I haven't had a chance to look, but seems like useful feedback to copy here. He mentioned his own example with integrating the markdown example with pubsub: https://github.com/norunners/hellovecty/tree/markdown

I need a good solid amount of time to actually sit down and think about how the entire redux store+dispatcher model can fit into a separate Vecty sub-package cleanly and work for all use cases. As part of that, I will obviously be looking at the above two packages.

If anyone has other packages / implementations in mind for a store / dispatcher model that you think I should look at, please let me know! I see this issue becoming more relevant in the coming weeks/months (i.e. I may actually start getting around to it soon..).

pdf commented 7 years ago

I've had some similar conversations. If you start on this, do let me know - I have a partial implementation that I was working on some time ago, that I may circle back around to once I get some other things off my plate if you don't get there first.

slimsag commented 7 years ago

@pdf If you could publish that partial implementation somewhere I think that'd be useful for me to look at preliminarily!

My expectation is that I will find a weekend with two spare days by accident and hammer out the best implementation I can. Then, I'll send that as a PR and we can all work from there to come out with a MVP implementation.


See also discussion starting at https://gophers.slack.com/archives/C0LBM1R0C/p1504915064000051

pdf commented 7 years ago

Honestly, I have no idea what state it's in, but I'll see if I can dig/clean it up.

marwan-at-work commented 7 years ago

@slimsag Redux by design highly depends on JavaScript's functional/dynamic features. For example, the connect function accepts any object and dynamically include that in your component's struct (this.props). So, a mere copy paste of the Redux design would be unintuitive for Go.

The challenge here is to reach the same goal that redux reaches, but in a Go-esque design.

So it's important to note that at the end of the day, this is what we want from a redux-type library:

  1. A single container for our application data.

  2. The ability for decoupled components to dispatch an update to that container, and all other containers would automatically/declaratively update themselves due to that dispatch.

  3. The ability to chain dispatches and side-effects through synchronous and asynchronous dispatches through middleware.

  4. The ability to do Hot Module Reloading since state is decoupled. This is a bigger concern and more on the GopherJS side.

@norunners's comments seem valid so far. He submitted a PR to vstore so it might a good point of discussion when it comes to implementation details. I have not fully settled on the design, but it seems to be in the right direction with his input and probably others as well.

guidorice commented 6 years ago

Hey all, I am a newbie when it comes to golang, but do have some experience working on a largish app using react+cycle+redux. I am really hoping that golang's features such as interfaces, goroutines and channels will, in practice, make the redux pattern less relevant. (I really hope so).

Does a "single container for our application data" make sense anymore in a concurrent environment? Is the Redux pattern just an artifact of javascript's peculiar history and world view? And a subset of javascript developers at that?

In any case, looking forward to using Vecty and gopherjs šŸ‘

marwan-at-work commented 6 years ago

@guidorice the redux pattern is more about separating state from components. For example, if you have two different Components that rely on the same piece of data (state), then updating that data from any component should automatically re-render all components that rely on this data without you having to manually do that in each component.

That being said, Go's primitives might be good enough to have the user write a redux pattern themselves without any library use. This part, imo, can be debated. A few people, including myself, have experimented with making a redux library for vecty. The lack of generics in Go makes a standard redux library a little more messy to implement. So I am still on the hunt for something that integrates well with Go's style.

guidorice commented 6 years ago

@marwan-at-work, yes well said. I guess I was just saying: I think it would be a mistake to standardize on Redux or bake it in in some way. Here is why, basically

https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367

Maybe consider making a Redux-like pattern a separate library and let people opt in.

As an example of a framework that got it right, is Mithril https://mithril.js.org/ . It lets you manage your state however you want, and as a result it is very easy to learn and get started with. Using mithril I find that by making components that are pure functions (style and appearance as a function of state), I generally don't feel like I need Redux. By again, just my opinion. :)

progrium commented 6 years ago

šŸ‘ on not baking a solution in. Plenty of apps don't have that kind of state to need Redux or Flux, and some need to do things differently entirely.

mar1n3r0 commented 3 years ago

@guidorice the redux pattern is more about separating state from components. For example, if you have two different Components that rely on the same piece of data (state), then updating that data from any component should automatically re-render all components that rely on this data without you having to manually do that in each component.

That being said, Go's primitives might be good enough to have the user write a redux pattern themselves without any library use. This part, imo, can be debated. A few people, including myself, have experimented with making a redux library for vecty. The lack of generics in Go makes a standard redux library a little more messy to implement. So I am still on the hunt for something that integrates well with Go's style.

Found your comment to be extremely useful on the conceptual side of things. Hope you guys don't mind bridging the topic between vugu, vecty and go-app so that the whole Go wasm ecosystem grows and learns from each other.

mar1n3r0 commented 3 years ago

on not baking a solution in. Plenty of apps don't have that kind of state to need Redux or Flux, and some need to do things differently entirely.

Fully agree, actually since state across all Go wasm frameworks is managed by native structs maybe state management libraries can be designed to be compatible with all frameworks at the same time in order to standardize the ecosystem.

mar1n3r0 commented 3 years ago

Iā€™m not a frontend dev, but I supervise some students that have been using overmindjs for state management. Thought Iā€™d mention it here as overmindjs takes a different approach, which seems to have some benefits that could possibly translate to a Go variant as well?

Here is a blog about it.

I am thinking of porting this to Go if I have the time and make it compatible with all existing Go wasm frameworks. The fact that it uses single state tree seems very favorable towards the Go struct type. Anyone else keen on the idea ?

norunners commented 3 years ago

@mar1n3r0 I'm definitely interested in the idea and the topic in general. There will be several areas where the API may need some reworking, due to the type safety. For example: (roughly)

let step = state.currentStep;
actions.updateStep(step + 1);
step := state.Int("currentStep")
actions.Call("updateStep", step + 1)
mar1n3r0 commented 3 years ago

@norunners I just found this as well.

https://github.com/luisvinicius167/godux