bigskysoftware / bigskysoftware/htmx

`hx-target` + `hx-swap="outerHTML"` causes errors with parallel `hx-get` requests

Open
#2,597 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
JavaScript
Stars
49.4k
Forks
1.7k
Avg merge
3d 22h
Merged PRs (30d)
30

Description

Demo code here of the issue: https://github.com/jwendel/scratch/tree/main/htmx-multi-request

possible related issue: https://github.com/bigskysoftware/htmx/issues/2440

## High-level
HTMX (`htmx.org@1.9.12`) is printing this in the Chrome console in my demo project if I switch quickly between the radio buttons:
```
TypeError: Cannot read properties of null (reading 'querySelector')
at htmx.js:903:46
at forEach (htmx.js:421:21)
at handleAttributes (htmx.js:898:13)
at insertNodesBefore (htmx.js:934:13)
at swapOuterHTML (htmx.js:1018:17)
at swap (htmx.js:1086:21)
at selectAndSwap (htmx.js:1150:24)
at doSwap (htmx.js:3626:25)
at handleAjaxResponse (htmx.js:3740:21)
at xhr.onload (htmx.js:3332:21)
```

And after this happens, the buttons that threw this error get stuck and stop sending hx-get requests to the server.

## Reason

Here is the problem HTML code:

```HTML

blue

green

content here

```

And the call to `/dostuff` returns:

```html

response!

```

Stepping through this a bunch, I believe the issue is that when you use `hx-target` along-side `hx-get`, HTMX remembers the target element (it does a query for it before sending the request), so when the XHR response comes in, it has a reference to the object (specifically the `responseInfo` object here: https://github.com/bigskysoftware/htmx/blob/15243b5d43e148934bbca7deb1028570afcd76ad/src/htmx.js#L3339. When the first response comes in, the div is replaced. When the second comes in, it tries to replace the remembered div, but it had been replaced in the DOM already (so it gives an error).

Steps to cause this:

1) You have 2 elements that set `hx-target` to the same target div
2) You set `hx-swap="outerHTML"` on both
3) Both elements issue XHR requests (`hx-get` in my case) in an overlapping fashion.

## Workarounds:

I think there are 2 workarounds

1) Don't use `hx-swap=outerHTML` if you can get multiple requests going at the same time. I switched the setup to use `hx-swap="innerHTML"` and it worked just fine with multiple requests.
2) use `hx-sync`. Specially I did `hx-sync="#updateme:replace"` on all the radio buttons and it resolved the issue by aborting the requests, so no request could try to update the `div` that was replaced before we get a response.

## Solution idea

`hx-target` shouldn't remember the full object at the start of the request (do the DOM query for it again).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.