go-app: Component level action trigger global level handler

The actionDemo component is used for action handler test only.
The problem is that both comp1 and comp2 value are changed when the “Inc” button of comp1 is clicked.

package comp

import (
	"fmt"
	"github.com/maxence-charriere/go-app/v9/pkg/app"
)

type (
	actionDemo struct {
		app.Compo
	}

	actionCompo struct {
		app.Compo
		FName string
		value int
	}
)

func (this *actionDemo) Render() app.UI {
	return app.Div().
		Body(
			&actionCompo{
				FName: "comp1",
			},
			&actionCompo{
				FName: "comp2",
			},
		)
}

func (this *actionCompo) OnMount(ctx app.Context) {
	ctx.Handle("value", func(context app.Context, action app.Action) {
		this.value += action.Value.(int)
	})
}
func (this *actionCompo) Render() app.UI {
	return app.Div().
		Body(
			app.Span().Body(
				app.Text(this.FName),
				app.Text(": "),
				app.Text(fmt.Sprintf("%d", this.value)),
				app.Button().
					Text("Inc").
					OnClick(func(ctx app.Context, e app.Event) {
						ctx.NewActionWithValue("value", 1)
					}),
				app.Button().
					Text("Des").
					OnClick(func(ctx app.Context, e app.Event) {
						ctx.NewActionWithValue("value", -1)
					}),
			))
}

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 15 (6 by maintainers)

Most upvoted comments

Well, when I need to transfer data between components that are not directly connected, I just use global / package level variables. The framework we made has a shared state which is based on the “page” (which is more like a scene) and most of the components “inside” either are dumb or have access to that shared state.

I/We may not use go-app the same way as others, or maybe not even as intended. We do not have an “input” or “select” component that gets wrapped by another “form” or “label” component in current projects. We would have an “address-entry” component, that gets part of an “order form”. Those then can use a component like a complex combo box with search and backend connection or such stuff. These get created by the parent and communicate through callbacks to update the parent’s state. In the end, all the data is always in Go, we don’t ever read data from the DOM outside the “internals” of a component, where it is sometimes needed. The DOM is just a “canvas” and in fact, I was already thinking about changing some stuff we render from using HTML elements to a simple canvas (we may be re-inventing flutter here lol).

There are mostly no interactions on the JavaScript level between components, either. I also kind of dislike using events because they are losing type information and convert data between Wasm and JS. Most of the time my credo is to “pretend that there is no java-script” and each external JS library used feels like a defeat to me.

One of our biggest app actually is just one component that has “scenes” and “states” that describe what “render” has to display. User input just updates the states, and the app renders the new state. This whole app will be part of another app later, that controls what the current “function” is (kind of like starting an application on your OS), but the controlling component has no clue about what this thing does. The controller may share something like a “notifications” or “status bar” or “log-panel” component. I had “events” for those before, but then I found it much more convenient just to have a global “status bar” or “logger” or “notifications” variable that gets transferred on component creation and is called using methods. Basically, I share state between components that way. Like the connection to the NATS-Server, which is just a global variable. Similar to how the “net/http” package keeps its internal connections globally but abstract this for the consumer. As there is also a guarantee that there is only one UI thread and code runs on that, you often do not even need to worry about concurrency.

I saw some people’s approaches to create or abstract a JavaScript/CSS framework like Bootstrap as “go-app” but I don’t see the use case for me. If I want to use a Vite/VueJS or React like framework, I would just use that and typescript. Go-App and Wasm to me is more like using wxWidgets and Python in the past.