delaneyj / datastar

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

data-on-load is being called repeatedly

samborkent opened this issue · comments

Hello, I was demoing this project to try to see if I could replace HTMX with the SSE extension in a personal project. Unfortunately, I immediately stumbled upon an issue.

I serve the web app as static (compressed) files embedded in my Go program. With HTMX I can do the following:

<body hx-post="/session" hx-trigger="load" hx-swap="none">

This sends a post request to the session endpoint once on page load to identify the session and create a cookie.

I thought the equivalent in datastar would be:

<body data-on-load="$$post('/session')">

However, this continuously posts requests. I tried adding the .once modifier as such:

<body data-on-load.once="$$post('/session')">

But this doesn't seem to do anything and request keep being send repeatedly.

How can I perform a post request once upon page load?

Much thanks in advance!

Yep, I just changed how plugins get applied. Same thing was happening with data-store. The correction is to remove the attribute after its applied at the plugin level. I'll make a PR in a few minutes.

v0.11.4 should fix your issue! Please confirm

Thank you for the quick response!

Maybe I misunderstand the framework, but it only works if I follow the Go example in your latest commit and return a SSE and a valid HTML element as response as such:

datastar.RenderFragment(datastar.NewSSE(w, r), elements.DIV())

I also tried to only write an OK response, flush the response writer, or send a SSE with an empty element, but that does not work. The above example is the minimal accepted response needed to stop the data-on-load attribute from triggering continously. The .once modifier does not affect this either.

I am unsure if this by design, as it is not mentioned in the example on the website. Also, I do not understand why I would need to send a SSE as reponse to a data-on-* attirbute, as this is not needed in HTMX and it seems unncessary, but maybe I am missing something.

At least I can continu with experimenting with Datastar now. I am curious to see what it can accomplish.

Not sure why you want to do a data-on-load but with no data, why wouldn't you just do what you want to do. I think I'm missing the ask.

if <body data-on-load="$$post('/session')"> doesn't need to update fragments, just do the handler and send no SSE events. The fetch connection will close with no issues.

The .once modifier does not affect this either.

The .once is meant to interact with builtin DOM events, load is a Datastar construct, so its not effected

I was using this to identify a session, create a cookie, and prepare some resources in the back-end for that session. As I serve my page as static files I use a file server as handler, so I couldn't do it there. I'll just wrap the file server in a middelware instead to do the session logic, I didn't need this using HTMX, but it might be a better solution anyway.

if doesn't need to update fragments, just do the handler and send no SSE events. The fetch connection will close with no issues.

As mentioned, if I don't send a SSE as response the data-on-load will still keep triggering repeatedly, which is not what I would expect.

Thank you for clarifying the .once modifier, that makes sense. I assumed it was equivalent to a HTML window load event.

@samborkent

https://datastar.fly.dev/examples/on_load has been updated to generate session data. I also release 0.11.5 and hopefully fixed the multi POST on load issue.

https://github.com/delaneyj/datastar/blob/main/backends/go/site/routes_examples_on_load.go#L28-L35 You can comment this out and the session will still get stored but obviously no update to the page will occur.

@delaneyj Thank you for the quick support! v0.11.5 unfortunately did not fix the issue, the post request on data-on-load is still send repeatedly if you do not return a response with SSE headers. In order to stop it from being send repeatedly you have to respond with the SSE headers:

w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
w.Header().Set("Content-Type", "text/event-stream")
w.(http.Flusher).Flush()

I've changed my code to use a middleware instead for session registration, so I don't need this at the moment. But I still think it is confusing that an on load attribute would trigger repeatedly if no SSE response is send. If this is by design I think explaining this in the docs would be a good idea.

Weird it works for me in Chrome. Maybe a vid chat working through the problem

Ah, I should have mentioned I tested on Firefox. I will try on Chrome to confirm if it works there and report back. :)

I tried in Brave (Chromium based, I don't have Chrome installed) and the behaviour is the same. On load only stops sending once it has received a SSE response. I also noticed that all datastar always sends a viewTransitionRefCounts URL parameter, what is the purpose of this?

I have decided to move back to HTMX + SSE extensions for now, as I could not get things to work as expected. Most of the issues were probably caused by the fact that I do not want to use the gostar package as I am using Templ, which has overlapping functionality.

To get broader adoption within the Go community I think it would be good to recreate the current examples using the Go standard library instead of using your own packages, which obscufate the inner workings. Then you can move the current examples to the gostar package, I think that would make more sense.

Also, a migration guide from HTMX to Datastar would be very useful. Next to the original issue for which I created this thread I was struggling to get exactly the same behaviour of the following HTMX snippet with Datastar:

<div id="entries" hx-ext="sse" sse-connect="/entries" sse-swap="message" hx-swap="beforeend">

Which adds an entry to the front-end whenever the back-end receives one. In the Datastar implementation, the front-end would receive my SSE's, but nothing would get swapped. I will check back on this package in the future.

I have decided to move back to HTMX + SSE extensions for now, as I could not get things to work as expected.

@samborkent I understand you position, especially if you already have been using HTMX

Most of the issues were probably caused by the fact that I do not want to use the gostar package as I am using Templ, which has overlapping functionality.

That should have no bearing on the examples. I could port the session on_load one to Templ if that'd help. Under the hood both are doing the same basic thing, but I like auto-completion and type safety. Before that though it'd be nice to know if you ran the datastar site locally. task -w should build and run.

To get broader adoption within the Go community I think it would be good to recreate the current examples using the Go standard library instead of using your own packages, which obscufate the inner workings. Then you can move the current examples to the gostar package, I think that would make more sense.

I'm backend agnostic but I understand your point

Also, a migration guide from HTMX to Datastar would be very useful. Next to the original issue for which I created this thread I was struggling to get exactly the same behaviour of the following HTMX snippet with Datastar:
<div id="entries" hx-ext="sse" sse-connect="/entries" sse-swap="message" hx-swap="beforeend">
Which adds an entry to the front-end whenever the back-end receives one. In the Datastar implementation, the front-end would receive my SSE's, but nothing would get swapped. I will check back on this package in the future.

https://data-star.dev/examples/merge_options using the after_element button should be what you want. If I need more examples, I'm happy to add.

The templating shouldn't matter, just wants getting sent to the browser.

Before that though it'd be nice to know if you ran the datastar site locally. task -w should build and run.

I should probably do this. I'm certain that would help me figuring out what I was doing wrong.

I'm backend agnostic but I understand your point

I meant the examples in backends/go specifically.

https://data-star.dev/examples/merge_options using the after_element button should be what you want. If I need more examples, I'm happy to add.

Ah, I missed that! That does cover the before end swap. But I was failing to get HTML swapped in at all.

I have limited time at the moment, but I will give it another go in the future as I do like the philosophy of Datastar. I'll then start by building the example website to learn.

Thank you for the help and your responsiveness!