vugu / vugu

Vugu: A modern UI library for Go+WebAssembly (experimental)
https://www.vugu.org
MIT License
4.8k stars 175 forks source link

Rendered() lifecycle hook not working for unknown reasons #224

Open PotatoesFall opened 2 years ago

PotatoesFall commented 2 years ago

Describe the bug https://www.vugu.org/doc/components describes a Rendered(vugu.RenderedCtx) method that gets called after rendered, I have found that this does not actually happen.

Software Versions Vugu version: latest (v0.3.4) Go version: go version go1.17.4 linux/amd64 Browser and version: Version 1.35.103 Chromium: 98.0.4758.102 (Official Build) (64-bit)

To Reproduce This component: shows Init, Compute, and (if destroyed) Destroy in the console, but not Rendered.

<div>
    <input type="text" />
    <label vg-content="c.Label"></label>
</div>

<script type="application/x-go">
type Input struct {
    Label string `vugu:"data"`
}

func (i *Input) Init(vugu.InitCtx) {
    fmt.Println(`init`)
}

func (i *Input) Compute(vugu.ComputeCtx) {
    fmt.Println(`compute`)
}

func (i *Input) Rendered(vugu.RenderedCtx) {
    fmt.Println(`rendered`)
}

func (i *Input) Destroy(vugu.DestroyCtx) {
    fmt.Println(`destroyed`)
}
</script>

Expected behavior Call Rendered after rendering the component and updating the DOM

Additional Notes I https://github.com/vugu/vugu/blob/24d8d4332371618c6f2b8881ae9f8d52fab8e3ca/lifecycle.go I can see that there is no invokeRendered() step here that can b. If somebody can point me to where it should be and what to look out for, I would love to add it myself.

PotatoesFall commented 2 years ago

Upon taking a closer look I found that the lifecycle hook for Rendered is called in https://github.com/vugu/vugu/blob/24d8d4332371618c6f2b8881ae9f8d52fab8e3ca/domrender/renderer-js-util.go. However this isn't working for me. I can't reproduce this in the playground since it seems to not support lifecycle hooks, does it need a vugu version bump?

https://play.vugu.org/?p=H4sIAAAAAAAC_2zQwWoDIRDG8XPmKT7mlLQkey-7XtpLD7nkCSJqRWhVdJSG0ncvkvSy7NG_84NhZhs6uj-aFMVFWdicztWzIgCgebKhK6K5mhKyQG7ZLaxz_gxGS0hx-j76xIp2ROMPl5QEVUozgh_anasfrxA9rr359sJWi-Yr_RJ9tGiwL3ga5oD3GGR_GKiMDfC8gEc7gTemX9NXbuLW4JG3zcVF64qza_Tft9Wbq1LSbY0e-W7m6X4f9RcAAP__m5y0VU4BAAA%3D

arvryna commented 2 years ago

@PotatoesFall : Thanks for your analysis, we will check and get back to you on this.

PotatoesFall commented 2 years ago

@arvryna I just checked, in a new project from the examples with the same components and it works there. For some reason in my project it's not working. I am having no other error messages in the console, and the component is for sure being rendered. Does it make a difference if I am using vgrun or compiling manually and serving an embedded .wasm file?

I will see if I can step by step reduce my project back to the example and see when it goes wrong. thanks for your fast reply either way.

PotatoesFall commented 2 years ago

@arvryna I have reproduced it here: https://github.com/PotatoesFall/vugu-rendered-problem

vgrun devserver.go produces this output in the browser console: image

PotatoesFall commented 2 years ago

My current workaround is to use Compute() and start a new goroutine that obtains a lock on the EventEnv, which I believe only happens after rendering is complete.

zoltanmakra commented 2 years ago

I think the issue is caused by the fact that invokeRendered (renderer-js.go) is called only on the root component, not all rendered components. I made a small fix for that, seems working in my app. You can check the change in here

zoltanmakra commented 2 years ago

@bradleypeabody, can you please check this fix. If it seems OK, I'll create a pull request.

bradleypeabody commented 2 years ago

@zoltanmakra Okay yeah that seems good to me. I'm not sure why you need to use the Rendered() call as opposed to Init or Compute but I agree the current behavior for Rendered() looks broken and the fix indicated here looks good.

zoltanmakra commented 2 years ago

Thank you. I created a pull request for the fix. Calling Rendered can be useful sometimes but it clearly indicates a workaround. For example this code is working fine in Firefox if you click on the label, edit the inputbox then press enter, but it causes deadlock in Chrome. It can be fixed by tampering with event handlers and Rendered.

PotatoesFall commented 2 years ago

For illustration, the Rendered() hook is necessary for me because the CSS library I am using (BeerCSS) requires a function to be called everytime a new input appears to apply certain JS to it. That's a flaw of the css library, but it shows why it might be necessary to use Rendered().

owenwaller commented 8 months ago

Looks to me like the change has never had a PR opened against it. See: https://github.com/vugu/vugu/compare/master...zoltanmakra:invoke-rendered-fix?expand=1

Has this been merged in?