Why is the spread operator required in this JSX and how does the resultant HTML use equal-to ("=") as the delimiter?

huangapple go评论79阅读模式
英文:

Why is the spread operator required in this JSX and how does the resultant HTML use equal-to ("=") as the delimiter?

问题

I used the online Babel REPL to transpile the following JSX into JavaScript:

JSX:

function Button({children, ...rest }) {
  return (
    <button {...rest}>
      {children}
    </button>
  )
}

JavaScript output:

function Button({ children, ...rest }) {
  return React.createElement("button", rest, children);
}

In the JavaScript, the {...rest} that I passed to the button element in JSX is simply passed as an object argument to the createElement function. If I use {rest} instead of {...rest}, why is it an invalid expression?

Invalid JSX:

function Button({children, ...rest }) {
  return (
    <button {rest}>
      {children}
    </button>
  )
}
  1. In the object destructuring in the function declaration, I have already collected all the properties other than children into the rest object, and every javascript object is a valid expression in JSX, isn't it? So what forces us to use {...rest} in JSX in the <button> element?

  2. My 2nd question is: when we use spread operator on an object in JavaScript, it spreads the object's key value pairs using a colon as the delimiter between the key and the value. But when we use the spread operator inside a JSX element, in the resultant HTML, how do the key value pairs get spread with = as the delimiter between the key and the value?

英文:

I used the online Babel REPL to transpile the following JSX into JavaScript:

JSX:

function Button({children, ...rest }) {
  return (
    &lt;button {...rest}&gt;
      {children}
    &lt;/button&gt;
  )
}

JavaScript output:

function Button({ children, ...rest }) {
  return React.createElement(&quot;button&quot;, rest, children);
}

In the JavaScript, the {...rest} that I passed to the button element in JSX is simply passed as an object argument to the createElement function. If I use {rest} instead of {...rest}, why is it an invalid expression?

Invalid JSX:

function Button({children, ...rest }) {
  return (
    &lt;button {rest}&gt;
      {children}
    &lt;/button&gt;
  )
}
  1. In the object destructuring in the function declaration, I have already collected all the properties other than children into the rest object, and every javascript object is a valid expression in JSX, isn't it? So what forces us to use {...rest} in JSX in the &lt;button&gt; element?

  2. My 2nd question is: when we use spread operator on an object in JavaScript, it spreads the object's key value pairs using a colon as the delimiter between the key and the value. But when we use the spread operator inside a JSX element, in the resultant HTML, how do the key value pairs get spread with = as the delimiter between the key and the value?

答案1

得分: 1

因为在JSX中不支持使用{rest}而应该使用{...rest},这是一个无效的表达式。

在JSX中,只能以以下方式使用花括号:

  • 直接放在元素的子元素内,例如 &lt;div&gt;{expression} static text&lt;/div&gt;
  • 用于指定属性的动态值,在等号 = 后面,例如 &lt;div className={dynamicClass}&gt;&lt;/div&gt;
  • 将对象的所有属性作为组件的props传递。

需要注意的是,对于最后一种用法,语法必须精确为 &lt;ComponentName {...object}&gt;

请参考:
https://react.dev/learn/javascript-in-jsx-with-curly-braces#where-to-use-curly-braces
https://react.dev/learn/passing-props-to-a-component#forwarding-props-with-the-jsx-spread-syntax

当我们在JavaScript中对对象使用扩展运算符时,它会使用冒号作为键和值之间的分隔符来展开对象的键值对。

不,冒号只在对象字面量中使用,与对象的内部表示无关。说扩展语法与冒号作为分隔符相关是不准确的。

但是,当我们在JSX元素内部使用扩展运算符时,在生成的HTML中,键值对是如何使用等号作为键和值之间的分隔符来展开的呢?

这个问题的前提是基于一个误解。扩展语法与JSX的属性传递语法完全不同。它们看起来可能相似,但功能不同。你可以通过将代码转译为React.createElement的调用来看出,事实上,所有的JSX都可以转译为React.createElement的嵌套调用。

英文:

> If I use {rest} instead of {...rest}, why is it an invalid expression?

Because that's not supported in JSX. You may only use curly braces in the following ways:

  • Directly inside the children of an element, e.g. &lt;div&gt;{expression} static text&lt;/div&gt;
  • To specify a dynamic value for an attribute, immediately following the = sign, e.g. &lt;div className={dynamicClass}&gt;&lt;/div&gt;
  • To forward all properties of an object as props to a component.

Note that for this last use case, the syntax must be exactly &lt;ComponentName {...object}&gt;

See also:

https://react.dev/learn/javascript-in-jsx-with-curly-braces#where-to-use-curly-braces
https://react.dev/learn/passing-props-to-a-component#forwarding-props-with-the-jsx-spread-syntax

> when we use spread operator on an object in JavaScript, it spreads the object's key value pairs using a colon as the delimiter between the key and the value

No, colons are just used in object literals and has nothing to do with the internal representation of an object. It is inaccurate to say spread syntax is related to colons as delimiters.

> But when we use the spread operator inside a JSX element, in the resultant HTML, how do the key value pairs get spread with = as the delimiter between the key and the value?

The premise here is based on a misconception. Spread syntax is completely different from JSX's syntax for forwarding props. They only look similar but have different functionality. You can already see from transpiling the code that forwarding props can be transformed to calls to React.createElement. In fact, all JSX can be transpiled to nested calls of React.createElement.

huangapple
  • 本文由 发表于 2023年5月28日 04:04:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76348819.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定