reagent-project / reagent

A minimalistic ClojureScript interface to React.js
http://reagent-project.github.io/
MIT License
4.75k stars 415 forks source link

Is there really no way to create an HTML attribute without a value? #606

Closed elektronik2k5 closed 3 months ago

elektronik2k5 commented 4 months ago

Hiccup seems to allow it: https://github.com/weavejester/hiccup/issues/162#issuecomment-529458775

But the same trick results in disabled="", which is not the same as disabled (without value). It is also non standard and fails HTML validation.

BTW, React's JSX allows this like hiccup: by passing an empty string as value.

Deraen commented 4 months ago

I wonder if React handles the empty string differently JSX vs createElement calls?

I think Reagent should be passing empty string value as-is to the React createElement, so I find it surprising it works different than JSX.

Deraen commented 4 months ago

disabled attribute is considered boolean by React and if value is true the attribute is added to the HTML element and if false it isn't.

A quick check on React demo shows that it is React itself that is adding the ="" to HTML: https://react.dev/reference/react-dom/components/input#usage image

Deraen commented 4 months ago

disabled and other boolean attributes also work differently to regular attributes If you try React demo with foobar="" it will add the empty string to the element as-is. I don't think there is way add the attribute without value in React JSX? Both foobar and foobar={true} give a warning about the attribute not being a boolean attribute.

Whoops commented 4 months ago

The empty string is explicitly allowed in the HTML 5 spec. I think whatever validator is telling you it isn't is wrong.

If the attribute is present, its value must either be the empty string or a value that is an ASCII case-insensitive match for the attribute's canonical name, with no leading or trailing whitespace.

Deraen commented 3 months ago

What the spec or validator doesn't really matter here. Reagent doesn't build the HTML.

Reagent just passes the element property maps to React which builds the HTML elements with the attributes.

As far as I understand React in this case:

If you HAVE to generate such HTML, you could do it with dangerouslySetInnerHTML.

If there is a case where React createElement or JSX allows something that can't be currently represented with Reagent "Hiccup" format, that would be Reagent problem, but I didn't find such cases yet.

elektronik2k5 commented 3 months ago

Thanks everyone - you're right and I'll close the issue now. In the proprietary codebase of my client, where we currently use TS, react@17 and Emotion, somehow empty strings as prop values do create attributes without values. That was the base of my assumption that it is in fact possible in react. But searching online and trying multiple online playgrounds with different versions of react, TS and Emotion I failed to create an attribute without a value. 🤷🏻‍♂️

Deraen commented 3 months ago

Could have changed in React 17 -> 18. I tested with 18 locally and React docs site is using 19.

elektronik2k5 commented 3 months ago

Update: mystery solved. React always creates an empty value. The issue, apparently, is that webkit based browsers (I tested on Chrome, Brave and Gnome's "Web") omit the empty attribute from the display in the DevTools inspector, which is very misleading. Also, this is a "feature" and not a bug: https://issues.chromium.org/issues/41311158#comment3

Unlike webkit, Firefox doesn't hide these.