Skip to content

Commit 057f8f3

Browse files
author
Sebastian Silbermann
committed
Add warning if you use inert=""
1 parent 7f5f16e commit 057f8f3

File tree

5 files changed

+94
-3
lines changed

5 files changed

+94
-3
lines changed

fixtures/attribute-behavior/AttributeTableSnapshot.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5427,7 +5427,7 @@
54275427
| Test Case | Flags | Result |
54285428
| --- | --- | --- |
54295429
| `inert=(string)`| (changed)| `<boolean: true>` |
5430-
| `inert=(empty string)`| (initial)| `<boolean: false>` |
5430+
| `inert=(empty string)`| (initial, warning)| `<boolean: false>` |
54315431
| `inert=(array with string)`| (changed)| `<boolean: true>` |
54325432
| `inert=(empty array)`| (changed)| `<boolean: true>` |
54335433
| `inert=(object)`| (changed)| `<boolean: true>` |

packages/react-dom-bindings/src/client/ReactDOMComponent.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,10 @@ let didWarnFormActionType = false;
8686
let didWarnFormActionName = false;
8787
let didWarnFormActionTarget = false;
8888
let didWarnFormActionMethod = false;
89+
let didWarnForNewBooleanPropsWithEmptyValue: {[string]: boolean};
8990
let canDiffStyleForHydrationWarning;
9091
if (__DEV__) {
92+
didWarnForNewBooleanPropsWithEmptyValue = {};
9193
// IE 11 parses & normalizes the style attribute as opposed to other
9294
// browsers. It adds spaces and sorts the properties in some
9395
// non-alphabetical order. Handling that would require sorting CSS
@@ -711,6 +713,19 @@ function setProp(
711713
if (!enableNewBooleanProps) {
712714
setValueForAttribute(domElement, key, value);
713715
break;
716+
} else {
717+
if (__DEV__) {
718+
if (value === '' && !didWarnForNewBooleanPropsWithEmptyValue[key]) {
719+
didWarnForNewBooleanPropsWithEmptyValue[key] = true;
720+
console.error(
721+
'Received an empty string for a boolean attribute `%s`. ' +
722+
'This will treat the attribute as if it were false. ' +
723+
'Either pass `false` to silence this warning, or ' +
724+
'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
725+
key,
726+
);
727+
}
728+
}
714729
}
715730
// fallthrough for new boolean props without the flag on
716731
case 'allowFullScreen':
@@ -2662,6 +2677,21 @@ function diffHydratedGenericElement(
26622677
continue;
26632678
case 'inert':
26642679
if (enableNewBooleanProps) {
2680+
if (__DEV__) {
2681+
if (
2682+
value === '' &&
2683+
!didWarnForNewBooleanPropsWithEmptyValue[propKey]
2684+
) {
2685+
didWarnForNewBooleanPropsWithEmptyValue[propKey] = true;
2686+
console.error(
2687+
'Received an empty string for a boolean attribute `%s`. ' +
2688+
'This will treat the attribute as if it were false. ' +
2689+
'Either pass `false` to silence this warning, or ' +
2690+
'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
2691+
propKey,
2692+
);
2693+
}
2694+
}
26652695
hydrateBooleanAttribute(
26662696
domElement,
26672697
propKey,

packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,11 @@ const importMapScriptEnd = stringToPrecomputedChunk('</script>');
347347
// allow one more header to be captured which means in practice if the limit is approached it will be exceeded
348348
const DEFAULT_HEADERS_CAPACITY_IN_UTF16_CODE_UNITS = 2000;
349349

350+
let didWarnForNewBooleanPropsWithEmptyValue: {[string]: boolean};
351+
if (__DEV__) {
352+
didWarnForNewBooleanPropsWithEmptyValue = {};
353+
}
354+
350355
// Allows us to keep track of what we've already written so we can refer back to it.
351356
// if passed externalRuntimeConfig and the enableFizzExternalRuntime feature flag
352357
// is set, the server will send instructions via data attributes (instead of inline scripts)
@@ -1402,6 +1407,18 @@ function pushAttribute(
14021407
return;
14031408
case 'inert': {
14041409
if (enableNewBooleanProps) {
1410+
if (__DEV__) {
1411+
if (value === '' && !didWarnForNewBooleanPropsWithEmptyValue[name]) {
1412+
didWarnForNewBooleanPropsWithEmptyValue[name] = true;
1413+
console.error(
1414+
'Received an empty string for a boolean attribute `%s`. ' +
1415+
'This will treat the attribute as if it were false. ' +
1416+
'Either pass `false` to silence this warning, or ' +
1417+
'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
1418+
name,
1419+
);
1420+
}
1421+
}
14051422
// Boolean
14061423
if (value && typeof value !== 'function' && typeof value !== 'symbol') {
14071424
target.push(

packages/react-dom/src/__tests__/ReactDOMAttribute-test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,35 @@ describe('ReactDOM unknown attribute', () => {
109109
);
110110
});
111111

112+
it('warns once for empty strings in new boolean props', async () => {
113+
const el = document.createElement('div');
114+
const root = ReactDOMClient.createRoot(el);
115+
116+
await expect(async () => {
117+
await act(() => {
118+
root.render(<div inert="" />);
119+
});
120+
}).toErrorDev(
121+
ReactFeatureFlags.enableNewBooleanProps
122+
? [
123+
'Warning: Received an empty string for a boolean attribute `inert`. ' +
124+
'This will treat the attribute as if it were false. ' +
125+
'Either pass `false` to silence this warning, or ' +
126+
'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
127+
]
128+
: [],
129+
);
130+
131+
expect(el.firstChild.getAttribute('inert')).toBe(
132+
ReactFeatureFlags.enableNewBooleanProps ? null : '',
133+
);
134+
135+
// The warning is only printed once.
136+
await act(() => {
137+
root.render(<div inert="" />);
138+
});
139+
});
140+
112141
it('passes through strings', async () => {
113142
await testUnknownAttributeAssignment('a string', 'a string');
114143
});

packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ describe('ReactDOMServerIntegration', () => {
754754
}
755755
});
756756

757-
itRenders('new boolean `true` attributes as strings', async render => {
757+
itRenders('new boolean `true` attributes', async render => {
758758
const element = await render(
759759
<div inert={true} />,
760760
ReactFeatureFlags.enableNewBooleanProps ? 0 : 1,
@@ -765,7 +765,22 @@ describe('ReactDOMServerIntegration', () => {
765765
);
766766
});
767767

768-
itRenders('new boolean `false` attributes as strings', async render => {
768+
itRenders('new boolean `""` attributes', async render => {
769+
const element = await render(
770+
<div inert="" />,
771+
ReactFeatureFlags.enableNewBooleanProps
772+
? // Warns since this used to render `inert=""` like `inert={true}`
773+
// but now renders it like `inert={false}`.
774+
1
775+
: 0,
776+
);
777+
778+
expect(element.getAttribute('inert')).toBe(
779+
ReactFeatureFlags.enableNewBooleanProps ? null : '',
780+
);
781+
});
782+
783+
itRenders('new boolean `false` attributes', async render => {
769784
const element = await render(
770785
<div inert={false} />,
771786
ReactFeatureFlags.enableNewBooleanProps ? 0 : 1,

0 commit comments

Comments
 (0)