当前位置: 首页 > 面试题库 >

React-分解时的defaultProps vs ES6默认参数(性能问题)

殳飞扬
2023-03-14
问题内容

我只是在我的 无状态功能组件 之一中设置默认值时遇到了一个关于React性能的问题。

此组件有defaultProps其定义row: false,但我不喜欢它,因为defaultProps在最后
的文件,这实际上使得它很难看到的。因此,我们不知道默认属性。因此,我将其直接移至函数声明,并使用ES6默认参数值对其进行了分配。

const FormField = ({
  row = false,
  ...others,
}) => {
  // logic...
};

但是随后我们与一位同事争论说这 是否是一个好主意 。因为这样做似乎很简单,但由于 react无法识别 默认值,因此对性能也可能有很大影响。

我相信在这种情况下,这是微不足道的。因为它是布尔值,而不是对象/数组,因此在 对帐 期间不会被视为不同的值。

但是,现在让我们来看一个更高级的用例:

const FormField = ({
  input: { name, value, ...inputRest },
  label = capitalize(name),
  placeholder = label,
  row = false,
  meta: { touched, error, warning },
  ...others,
}) => {
  // logic...
};

在此,我基于placeholderfrom
的值label,其本身基于input.name。将ES6解构与参数的默认值一起使用可使整件事非常容易编写/理解,并且就像一个魅力。

但这是个好主意吗?如果没有,那么您将如何正确执行呢?


问题答案:

我在Discord #reactiflux频道上与几个人进行了交谈,实际上得到了我想要的答案。

React组件基本上有三个用例,在其中一些中,解构参数会影响性能,因此了解幕后情况很重要。

无状态功能组件

const MyComponent = ({ name = 'John Doe', displayName = humanize(name), address = helper.getDefaultAddress() }) => {
  return (
    <div>{displayName}</div>
  );
};

这是一个无状态的功能组件。没有状态,它是有功能的,因为它不是Class实例,而是简单的函数。

在这种情况下,没有生命周期,您不能有componentWillMountshouldComponentUpdateconstructor那里。而且由于没有生命周期的管理,因此对性能没有任何影响。此代码是完全有效的。有些人可能更喜欢displayName在函数体内处理默认值,但最终并不重要,它不会影响性能。

无状态非功能组件

(不要这样做!)

class MyComponent extends React.Component {
    render() {
        const { name = 'John Doe', displayName = humanize(name), address = helper.getDefaultAddress() } = this.props;
        return (
            <div>{displayName}</div>
          );
    }
}

这是无状态的非功能组件。没有状态,但由于是状态,所以它不是“功能性”的class。并且由于它是一个扩展类,React.Component所以它意味着您将拥有一个生命周期。你可以有componentWillMountshouldComponentUpdateconstructor有。

而且,由于它具有生命周期,因此编写此组件的方式很 糟糕 。但为什么?

简而言之,React提供了一个defaultProps属性来处理默认的props值。实际上,在处理非功能组件时最好使用它,因为所有依赖的方法都将调用它this.props

先前的代码段创建了名为name和的新局部变量displayName,但是
默认值仅适用于此render方法!。如果您希望将默认值应用于每种方法,例如React生命周期中的默认值(shouldComponentUpdate,等等),则
必须 使用defaultProps相反的值。

因此,先前的代码实际上是一个错误,可能导致对的默认值的误解name

要获得相同的行为,应改用以下方法:

class MyComponent extends React.Component {
    render() {
        const { name, displayName = humanize(name), address } = this.props;
        return (
            <div>{displayName}</div>
          );
    }
}

MyComponent.defaultProps = {
    name: 'John Doe',
    address: helper.getDefaultAddress(),
};

这个更好。因为John Doe如果未定义名称,它将始终存在。address还处理了默认值,但不处理displayName…为什么?

好吧,我还没有找到解决这个特殊用例的方法。因为displayName应当基于name属性,所以我们在定义时无法访问(AFAIK)defaultProps。我看到的唯一方法是render直接在方法中处理它。也许有更好的方法。

我们的address属性没有这个问题,因为它不是基于MyComponent属性,而是依赖于完全独立的东西,不需要道具。

有状态的非功能组件

它的工作原理与“无状态非功能组件”相同。因为仍然存在生命周期,所以行为将是相同的。state组件中有一个额外的内部组件这一事实不会改变任何东西。

我希望这有助于理解对组件使用解构时的情况。我真的很喜欢这种功能方式,它更简洁,恕我直言(为简单起见,+ 1)。

您可能更喜欢始终使用defaultProps,无论是使用功能组件还是非功能组件,它都是有效的。(+1为一致)

只要注意“需要”使用的非功能组件的生命周期即可defaultProps。但是最后选择总是你的;)

编辑10-2019 :defaultProps最终将在将来某个时候从React
API中删除,请参阅和https://github.com/reactjs/rfcs/pull/107用于RFC。



 类似资料:
  • 问题内容: 为什么这段代码会引发SyntaxError? 尽管以下代码段运行时没有可见错误: 问题答案: 必须将所有必需的参数放在任何默认参数之前。仅仅是因为它们是强制性的,而默认参数不是必需的。从语法上讲,如果允许使用混合模式,解释器将 无法 决定哪些值与哪些参数匹配。如果参数的输入顺序不正确,则会引发A : 让我们使用您的函数来查看关键字参数。 假设其允许声明函数如上,然后使用上述声明,我们可

  • 问题内容: 当我运行它时,它拒绝“ def a(…”,并用红色突出显示“(”。我不知道为什么。 问题答案: 让我在这里澄清两点: 首先,非默认参数不应跟随默认参数,这意味着您无法在函数中定义。在函数中定义参数的正确顺序为: 位置参数或非默认参数,即 关键字参数或默认参数,即 仅关键字参数,即 var-keyword参数,即 是位置参数 是可选参数 是关键字参数 是列表参数 仅限关键字 是var-k

  • 我们知道,在调用函数时如果不指定某个参数, Python 解释器会抛出异常。为了解决这个问题,Python 允许为参数设置默认值,即在定义函数时,直接给形式参数指定一个默认值。这样的话,即便调用函数时没有给拥有默认值的形参传递参数,该参数可以直接使用定义函数时设置的默认值。 Python 定义带有默认值参数的函数,其语法格式如下: def 函数名(...,形参名,形参名=默认值):     代码块

  • 本文向大家介绍Lua 默认参数,包括了Lua 默认参数的使用技巧和注意事项,需要的朋友参考一下 示例 该功能是一个简单的功能,并且效果很好。但是,如果我们刚刚打电话会发生什么sayHello()呢? 那不是很好。有两种解决方法: 您立即从函数返回: 您设置默认参数。 为此,只需使用此简单表达式 这个成语name = name or "Jack"之所以有效,是因为or在Lua中发生短路。如果左侧的项

  • 函数调用可能通常传递参数的特定值。程序员可以将该参数指定为默认参数,程序员可以提供这个参数的默认值。当函数调用中省略默认参数时,默认参数值自动传递给被调用函数。 默认参数必须是函数参数表中最右边(尾部)的参数。调用具有两个或多个默认参数的函数时,如果省略的参数不是参数表中最右边的参数,则该参数右边的所有参数也应省略。默认参数应在函数名第一次出现时指定,通常是在函数原型中。默认值可以是常量、全局变量

  • 问题内容: 我读到React非常快。最近,我写了一个应用程序来测试对角的反应。不幸的是,我发现反应的表现要慢于角度反应。 http://shojib.github.io/ngJS/#/speedtest/react/1 这是react的源代码。我是新来的人。我确定我的反应代码在这里做错了。我发现它异常缓慢。 https://jsbin.com/viviva/edit?js,输出 看看是否有任何反应