-
Notifications
You must be signed in to change notification settings - Fork 46.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Decide on the desired behavior when a boolean value is passed to an unknown prop. #10521
Comments
What are the properties that expect "true" or "false" values? I know the ARIA boolean attributes do but from a cursory look at https://www.w3.org/TR/wai-aria/states_and_properties, all of the boolean attributes default to That means we could do ="true" for true and omit the attribute for false. I think that might be compatible for almost every case. In HTML, any string is treated as a boolean value so ="true" is valid. |
Attempting to summarize the proposals and pros/cons so far: Option 1: Pros:
Cons:
Option 2: Pros:
Cons:
Option 3: Pros:
Cons:
Edit: Please correct anything I missed, thanks to everyone who has chimed in about this. |
So IIUC as far as we know option 2 has no downsides and will never cause the wrong behavior that we know of. Is that right? If so, that sounds the most compelling to me. |
@spicyj setting boolean attributes to "true" isn't valid according to the HTML spec section on boolean attributes.
This is especially a problem with custom elements, as outlined in #9230.
What I'm suggesting is this:
|
@spicyj Actually... for a prior version of the custom attributes feature, @gaearon and I dug through the spec and found all of the attributes that expected true/false strings. They are: HTML:
SVG:
|
@aweary It has the correct behavior though, right? In practice, you would test .hasAttribute() since it is common to do checked="" and common to do checked="". @nhunzaker Ah, so like autoComplete={false} would need to become autocomplete="false"? Good find. |
@spicyj the existing behavior isn't correct because it renders |
I think what @aweary is suggesting makes sense, we already have the stringy boolean attributes in the list. We'd still allow all boolean values through in the filter, but change the way the boolean attribute is actually written in |
@aweary Still, I'm curious about the behavior here. Why does |
@nhunzaker it's weird, I know. Boolean attributes are kind of spec'd as "they should exist, or they shouldn't" so using At least, that's my interpretation. I can't speak to the motives of the spec authors 😄 |
👍 maybe we could coerce known enumerable attributes expecting booleans to strings earlier in the code path so that |
@sebmarkbage pointed out we don't actually have a consistent behavior in 15.* for booleans - sometimes they get stringified, sometimes maybe not. I'll let him add some context on why we thought of stringifying as the default in 16.0. |
To clarify my position, I'm mostly advocating for following the spec for unknown boolean attributes. If there are compatibility concerns with some set of known/previously-known attributes, that totally makes sense, and I can get behind special casing that behavior. I just think the default approach for attributes we have no information about should be consistent with the spec if possible. |
I was arguing that conformance to the spec in a case like this doesn't matter – as far as I can tell, attributes described by that spec behave as "if the attribute is present, it's on; if it's not, it's off". Even though the spec says true/false isn't correct, I interpret that as a warning against writing "true" in HTML because then you would be liable to think "false" would work as false. That isn't the case so writing "true" manually is a refactoring hazard in HTML, but that argument doesn't translate over to React. If "true" behaves the same as "" in all browsers, I don't see the downside of passing "true". |
I'm arguing that it's safer to conform to the spec for unknown attributes that accept booleans, especially in the context of future boolean attributes that may depend on the behavior defined in the spec. This is also a concern with custom elements as outlined in #9230 (maybe @robdodson can provide more insight here). More importantly, it does matter for boolean attributes when the value is What are the downsides? If we already have a whitelist of boolean attributes we can special case those to stringify if we have compatibility concerns until the next major and treat truly unknown attributes as the spec describes. |
The (only?) advantage of "true"-vs-omit is that |
If we want to support enumerated attributes with boolean values (so @nhunzaker that, and |
I was also arguing that false should omit the attribute for unknown attributes. |
But @spicyj said:
If we did an empty string, I think we could remove every entry from the HTMLPropertyConfig for We'd need like 7 exceptions for string values, but from a design standpoint, I like that it removes code. |
@spicyj Hah! Sorry. Spoke for you :) |
@spicyj I somehow skimmed over that part, and I even quoted it 😄 thanks for clarifying. @nhunzaker If we want to keep stringifying boolean attributes that were already stringified in 15* we'd probably need to keep the whitelist right? I'm not sure if that point is clear or not though, how concerned are we about that? But even then, we'd be able to remove it in the following major, which would be nice. |
Oh wait, |
Right. I think we can safely remove it. This could be non-breaking. |
Not sure if I'm following exactly what you're discussing, but I think removing HAS_BOOLEAN_VALUE is breaking since it changes what happens when you pass non-boolean values to it. |
Ah you're correct, for context this happens here: So the breaking change would be that you could technically assign a string value to one of these attributes, where you'd need to pass a boolean to get the expected behavior (an empty string assuming we go with @aweary's approach). But maybe this is fine? It wouldn't be spec compliant, but as @spicyj suggested earlier, maybe presence is enough. Taking So at best we're spec compliant, but at worst everything works as expected (right?). It's a breaking change to the markup because whatever string you pass gets used, like https://codepen.io/nhunzaker/pen/oeyVqM Unless, of course, this is not consistent beyond my |
I think the meaningful difference is that today (with HAS_BOOLEAN_VALUE) '' is counted as false but it wouldn't be if we count the attribute as unknown. Everything else probably doesn't matter in practice. |
Note that this list is incorrect, I believe |
Thank you! I've sent out a PR that addresses this (#10531)
Yep. So if we made this the default behavior, we could just add a flag that said "Always stringify this property", it would target 7 attributes: |
Or So really, serializing |
The canonical way of expressing this is easy to find. You simply use the property instead of the attribute and then read the attribute. My preference is keeping the attribute consistent with what you'd get from using the property. |
How does this high-level approach sound:
|
This makes the most sense but feels unfortunate :/ why is the DOM so dang wonky :P Would this silently fail in v17 tho? |
Maybe we could keep that warning indefinitely? It shouldn't be too costly as a DEV-only check. |
The plan described by @aweary in #10521 (comment) sounds good to me. |
Moving the discussion from comments in #10509 to this issue.
The text was updated successfully, but these errors were encountered: