Improve error message when not providing a value for JSX key (#12983)

* Improve error message when not providing a value for key

* Update packages/babel-plugin-transform-react-jsx/src/create-plugin.js

Show location of attribute instead of only the path

Co-authored-by: Huáng Jùnliàng <jlhwung@gmail.com>

* Change error message to be less aggressive

* Throw error when runtime is "classic"

Co-authored-by: Huáng Jùnliàng <jlhwung@gmail.com>
This commit is contained in:
hajnalbendeguz 2021-03-16 13:02:08 +01:00 committed by GitHub
parent 6e1e00388b
commit 281acd6448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 17 deletions

View File

@ -341,9 +341,9 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
} }
} }
function accumulateAttribute(array, node) { function accumulateAttribute(array, attribute) {
if (t.isJSXSpreadAttribute(node)) { if (t.isJSXSpreadAttribute(attribute.node)) {
const arg = node.argument; const arg = attribute.node.argument;
// Collect properties into props array if spreading object expression // Collect properties into props array if spreading object expression
if (t.isObjectExpression(arg)) { if (t.isObjectExpression(arg)) {
array.push(...arg.properties); array.push(...arg.properties);
@ -353,26 +353,46 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
return array; return array;
} }
const value = convertAttributeValue(node.value || t.booleanLiteral(true)); const value = convertAttributeValue(
attribute.node.name.name !== "key"
? attribute.node.value || t.booleanLiteral(true)
: attribute.node.value,
);
if (t.isStringLiteral(value) && !t.isJSXExpressionContainer(node.value)) { if (attribute.node.name.name === "key" && value === null) {
throw attribute.buildCodeFrameError(
'Please provide an explicit key value. Using "key" as a shorthand for "key={true}" is not allowed.',
);
}
if (
t.isStringLiteral(value) &&
!t.isJSXExpressionContainer(attribute.node.value)
) {
value.value = value.value.replace(/\n\s+/g, " "); value.value = value.value.replace(/\n\s+/g, " ");
// "raw" JSXText should not be used from a StringLiteral because it needs to be escaped. // "raw" JSXText should not be used from a StringLiteral because it needs to be escaped.
delete value.extra?.raw; delete value.extra?.raw;
} }
if (t.isJSXNamespacedName(node.name)) { if (t.isJSXNamespacedName(attribute.node.name)) {
node.name = t.stringLiteral( attribute.node.name = t.stringLiteral(
node.name.namespace.name + ":" + node.name.name.name, attribute.node.name.namespace.name +
":" +
attribute.node.name.name.name,
); );
} else if (t.isValidIdentifier(node.name.name, false)) { } else if (t.isValidIdentifier(attribute.node.name.name, false)) {
node.name.type = "Identifier"; attribute.node.name.type = "Identifier";
} else { } else {
node.name = t.stringLiteral(node.name.name); attribute.node.name = t.stringLiteral(attribute.node.name.name);
} }
array.push(t.inherits(t.objectProperty(node.name, value), node)); array.push(
t.inherits(
t.objectProperty(attribute.node.name, value),
attribute.node,
),
);
return array; return array;
} }
@ -411,14 +431,22 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
case "__self": case "__self":
if (extracted[name]) throw sourceSelfError(path, name); if (extracted[name]) throw sourceSelfError(path, name);
/* falls through */ /* falls through */
case "key": case "key": {
extracted[name] = convertAttributeValue(attr.node.value); const keyValue = convertAttributeValue(attr.node.value);
if (keyValue === null) {
throw attr.buildCodeFrameError(
'Please provide an explicit key value. Using "key" as a shorthand for "key={true}" is not allowed.',
);
}
extracted[name] = keyValue;
break; break;
}
default: default:
attribs.push(attr.node); attribs.push(attr);
} }
} else { } else {
attribs.push(attr.node); attribs.push(attr);
} }
} }
@ -511,7 +539,7 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
buildCreateElementOpeningElementAttributes( buildCreateElementOpeningElementAttributes(
file, file,
path, path,
openingPath.node.attributes, openingPath.get("attributes"),
), ),
...t.react.buildChildren(path.node), ...t.react.buildChildren(path.node),
]); ]);

View File

@ -0,0 +1,2 @@
var x = [<div key></div>];

View File

@ -0,0 +1,3 @@
{
"throws": "Please provide an explicit key value. Using \"key\" as a shorthand for \"key={true}\" is not allowed."
}

View File

@ -0,0 +1,2 @@
var x = [<div key></div>];

View File

@ -0,0 +1,3 @@
{
"throws": "Please provide an explicit key value. Using \"key\" as a shorthand for \"key={true}\" is not allowed."
}