【问题标题】:What does ...rest mean in React JSX?...rest 在 React JSX 中是什么意思?
【发布时间】:2021-09-27 04:55:52
【问题描述】:

查看这个 React Router Dom v4 示例 https://reacttraining.com/react-router/web/example/auth-workflow 我看到 PrivateRoute 组件像这样解构了一个 rest prop

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>
    )
  )}/>
)

我想确定{ component: Component, ...rest } 的意思是:

props,获取 Component 属性,然后将所有其他属性提供给您,并将props 重命名为rest,这样您就可以避免传递给路由render 函数的属性出现命名问题

我说的对吗?

【问题讨论】:

标签: javascript reactjs react-router


【解决方案1】:

抱歉,我意识到我的第一个答案(虽然希望仍然提供有用/额外的上下文)没有回答您的问题。让我再试一次。

你问:

我想确定{ component: Component, ...rest } 的意思是:

props 获取Component 属性,然后将所有其他props 分配给 您,并将 props 重命名为 rest,这样您就可以避免使用 props 传递给路由 render 函数

您的解释并不完全正确。不过,根据您的想法,听起来您至少知道这里发生的事情相当于某种 object destructuring(请参阅第二个答案和那里的 cmets 以获得更多说明)。

为了给出准确的解释,让我们将{ component: Component, ...rest } 表达式分解为两个独立的操作:

  1. 操作 1: 找到在 props 上定义的 component 属性(注意:小写 component)并将其分配到我们称之为Component 的状态(:大写C组件)。
  2. 操作 2: 然后,获取在 props 对象上定义的所有剩余属性,并将它们收集到一个名为 rest 的参数中。

重要的是,您没有将 props 重命名为 rest。 (这也与尝试“避免将props 传递给路由render 函数的命名问题”无关。)

rest === props;
// => false

您只是将props 对象上定义的属性的其余部分(因此该参数命名为该参数)转换为一个名为rest 的新参数。


示例用法

这是一个例子。假设我们有一个对象“myObj”,定义如下:
const myObj = {
  name: 'John Doe',
  age: 35,
  sex: 'M',
  dob: new Date(1990, 1, 1)
};

对于此示例,将props 视为具有与myObj 中所示相同的结构(、属性和值)可能会有所帮助。现在,让我们编写以下作业。

const { name: Username, ...rest } = myObj

上面的语句相当于两个变量(或者,我猜是常量)的声明赋值。该语句可以被认为是:

获取myObj 上定义的属性name 并将其值分配给一个新的 我们称之为Username的变量。然后,取其他任何属性 在myObjagesexdob)上定义并收集它们 到分配给我们命名为rest的变量的新对象中。

Usernamerest 记录到console 将确认这一点。我们有以下内容:

console.log(Username);
// => John Doe
console.log(rest);
// => { age: 35, sex: 'M', dob: Mon Jan 01 1990 00:00:00 GMT-0800 (PST) }

旁注

你可能想知道:

为什么要费尽心思取消 component 属性 只是用大写字母“C”重命名Component

是的,这似乎很微不足道。而且,虽然它是标准的 React 实践,但其框架上的所有 Facebook's documentation 都是这样编写的,这是有原因的。也就是说,使用 JSX 呈现的自定义组件的资本化本身与其说是一种实践,不如说是必要的。做出反应,或者更准确地说,JSX is case-sensitive。插入的没有大写首字母的自定义组件不会呈现给 DOM。这正是 React 定义自己以识别自定义组件的方式。因此,如果该示例没有另外将从props 提取的component 属性重命名为Component&lt;component {...props} /&gt; 表达式将无法正确呈现。

【讨论】:

  • 你应该是可以重写 React Docs 的人,你的回答显示了对教学的热情,它涵盖了初学者的每一个细节,同时保持一切简单。
  • 我只是为你创造了一个赏金,这是我所能做的,享受它:)
【解决方案2】:

它允许您在一个简洁的表达式中“传播”所有props。例如,假设您的PrivateRoute 组件收到的props 看起来像

// `props` Object:
{
  thing1: 'Something',
  thing2: 'Something else'
}

如果您想进一步将这些项目(iething1thing2)传递给嵌套的 &lt;Component /&gt; 标记,并且您不熟悉 object spread 语法,你可以写:

<Component
  thing1={ props.thing1 }
  thing2={ props.thing2 } />

不过,{ ...props } 语法允许您传播 props 对象,就像传播 值数组(例如,[...vals])。换句话说,下面的 JSX 表达式和上面的表达式是完全等价的。

<Component { ...props } />

【讨论】:

  • 虽然相关,但不要将 JSX 的 spread 语法与 rest properties 混用。
  • “它可以让你在一个简洁的表达式中“传播”所有的道具。” 这是不对的。 ...rest in { component: Component, ...rest } 收集对象 rest 中的所有其他属性。问题是关于...rest,而不是{...props}
  • 正如 Felix 所指出的,JSX 中的(非标准)对象 spread 运算符和 rest_/_spread 运算符之间存在区别ECMAScript 2015 规范中定义的运算符。一方面,尝试在非 React 环境(例如,浏览器控制台)中编写类似{ ...myObj } 的内容会抛出SyntaxError。尽管如此,ES6 的 rest_/_spread 提供了一个有用的概念框架来思考 JSX 的对象 spread
【解决方案3】:

让我们保持简单:在 JavaScript 中,如果 "key: value" 对是相同的, obj={account:account}obj={account} 相同。因此,当将 props 从父组件传递给子组件时:

const Input = ({name,label,error, ...rest}) => {
  return (
    <div className="form-group">
      <label htmlFor={name}>{label}</label>
      <input
        {...rest}
        autoFocus
        name={name}
        id={name}
        className="form-control"
        aria-describedby="emailHelp"
      />
    </div>
  );
};
export default Input;

您将传递 其余的道具

label={label} placeholder={placeholder} type={type}

【讨论】:

    猜你喜欢
    • 2017-10-09
    • 1970-01-01
    • 2021-06-26
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 2017-06-11
    相关资源
    最近更新 更多