为什么getDerivedStateFromProps是静态方法?

Hem*_*ari 5 javascript reactjs react-native

我尚未对静态getDerivedStateFromProps进行研究,因此我试图了解这一点。

我了解React通过引入一种称为静态getDerivedStateFromProps()的新生命周期方法,在React v16 +中已弃用componentWillReceiveProps。好的,但是想知道为什么React已经改为静态方法而不是普通方法。

为什么

   static getDerivedStateFromProps(nextProps, prevState){

   }
Run Code Online (Sandbox Code Playgroud)

为什么不

   getDerivedStateFromProps(nextProps, prevState){

   }
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么它是静态方法。

sup*_*upi 14

要了解 React 试图通过静态方法实现什么,您应该很好地理解以下内容:

  1. 副作用
  2. 为什么在 componentDidMount 钩子之前异步代码被认为是不好的方法
  3. 异步渲染
  4. 静态方法如何帮助阻止不纯和异步编码

  1. 副作用只不过是在范围之外操纵任何数据。因此,getDerivedStateFromProps 中的副作用将意味着对其自身局部变量以外的任何其他变量的更改。

不会引起副作用的函数称为纯函数,对于它们的参数,它们在被操作之前被克隆,从而保留这些参数指向的对象的状态。

这些函数只是从它们的范围内返回修改后的值,调用者可以用返回的数据决定操作过程。


  1. 在像 React 这样的库中引入自定义异步代码并使用自己的生命周期流并不是一个好主意。它应该在适当的时候小心地插入。让我们通过分析自定义类组件的组件创建生命周期来理解为什么(为了保持简短,让我们考虑它也是根元素)。

一开始 ReactDOM.render 方法调用 react.createElement() 方法调用。

react.createElement() => 调用 new ClassElement(props) 构造函数 => 返回 ClassElement 实例。

在构造函数调用之后, react.createElement() 调用 ClassElement.getDerivedStateFromProps(props) 方法调用。

上述方法返回后, react.createElement() 调用 instance.render() 方法。

(这个可以跳过)

接下来是其他同步调用,例如与虚拟 DOM 进行比较和更新真实 DOM 等,并且没有提供挂钩来利用这些调用(主要是因为没有强烈的需求)。这里需要注意的一个关键点是 JavaScript 执行、真实 DOM 更新和 UI 绘制——所有这些——都发生在浏览器的单个线程中,从而迫使它们同步。这是您可以编写同步内容的原因之一,例如:

let myDiv = document.getElementbyID("myDiv");
myDiv.style.width = "300px"; // myDiv already holds a reference to the real DOM element
console.log(myDiv.style.width); // the width is already set!
Run Code Online (Sandbox Code Playgroud)

因为您知道在每个语句的末尾,前面的语句是在 DOM 和浏览器窗口(我的意思是 UI)中完成的。

最后,render 方法返回后,react.createElement() 调用 componentDidMount 成功标记生命周期结束。既然已经结束,componentDidMount 自然是连接异步和非纯函数的最佳连接点。

我们必须明白的是,生命周期方法出于性能和灵活性的原因不断调整,并且完全在 React 工程师的控制之下。这不仅适用于 React,事实上它适用于任何第三方代码的流程。因此,引入不纯函数或异步调用可能会导致问题,因为您将迫使 React 工程师谨慎进行优化。

例如,如果 React 工程师决定在单个生命周期流中运行 getDerivedStateFromProps 两次或更多次,那么不纯函数和异步调用都会被触发两次或更多次,直接影响应用程序的某些部分。然而对于纯函数,这不会成为问题,因为它们只返回值,并且由 React 工程师决定在多个 getDerivedStateFromProps 调用中的过程(他们可以简单地丢弃所有返回值直到最后一次调用并利用最后一个)。


  1. 另一个例子是,如果 React 工程师决定使渲染调用异步会怎样。也许他们想要将所有的渲染调用(从父级到所有嵌套的子级)集中起来并异步触发它们以提高性能。

现在这意味着在渲染方法中或在它之前编写的异步调用(如在构造函数或 getDerivedStateFromProps 中)可能会干扰渲染过程,因为异步过程完成的不可预测性。一个可以在另一个之前或之后完成,不可预测地触发它们各自的回调。这种不可预测性可以通过多重渲染、不可预测状态等形式反映出来。

重要的是,这两个想法不仅仅是示例,而是由 React 工程师表达为未来可能的优化方法。在这里阅读:https : //stackoverflow.com/a/41612993/923372


  1. 尽管如此,React 工程师知道那里的开发人员仍然可以编写异步代码或不纯的函数,为了阻止这种情况,他们将生命周期方法之一设为静态。构造函数、render、getSnapshotBeforeUpdate、componentDidMount 和 componentDidUpdate 方法不能是静态的,因为它们需要访问实例属性,如 this.state、this.props、其他自定义事件处理程序等(构造函数初始化它们,render 使用它们来控制 UI逻辑,其他生命周期方法需要这些来与早期状态进行比较)

但是,考虑到 getDerivedStateFromProps,如果先前的 props 与当前的 props 不同,则提供此钩子仅用于返回状态的更新克隆。根据这个定义,这听起来很纯粹,不需要任何对实例属性的访问。让我们分析一下原因。

为了让这个钩子工作,开发者首先需要将之前的 props 存储在实例状态中(比方说,在构造函数调用中)。这是因为 getDerivedStateFromProps 接收实例状态以及新的 props 作为参数。然后,开发人员可以继续比较所需的属性并返回状态的更新克隆(无需访问 this.props 或 this.state)。

通过将 getDerivedStateFromProps 设为静态,React 不仅迫使您编写纯函数,而且还使编写异步调用变得困难,因为您无法访问此方法中的任何实例。通常异步调用会提供一个回调,它很可能是一个实例方法。

现在这并不意味着开发人员不能编写它们,相反,这只是使其变得困难并被迫远离此类方法。


一个简单的经验法则是在第三方引发的流量期间远离不纯和异步的功能方法。您应该只在此类流程结束时引入此类方法。


Ngu*_*You 6

根据此提案的描述:

该提议旨在降低编写异步兼容的React组件的风险。

它通过消除<sup>1</sup> 当前API中的许多潜在陷阱来实现此目的,同时保留了API支持的重要功能。我相信这可以通过结合以下方式实现:

  1. 选择用途更明确,用途更有限的生命周期方法名称。

  2. 将某些生命周期设为静态可防止对实例属性的不安全访问。

在这里

用静态方法替换容易出错的渲染阶段生命周期挂钩, 以使其更容易编写异步兼容的React组件。

最终,经过大量讨论,此处还正式描述了使用静态方法的目标:

该提案的目的是减少编写异步兼容的React组件的风险。我相信,可以通过消除当前API中的许多潜在陷阱来实现,同时保留API支持的重要功能。可以通过以下组合来完成:

  1. 选择用途更明确,用途更有限的生命周期方法名称。

  2. 将某些生命周期设为静态可防止对实例属性的不安全访问。

无法检测或防止所有副作用(例如,全局/共享对象的突变)。


Sam*_*nen 5

您不应该接触该方法中的任何内部数据,因此它被定义为静态。这样,您就没有可以触摸的对象,并且您\xe2\x80\x99 唯一允许做的事情就是使用提供的 previous state 和 next 属性来执行您\xe2\x80\x99 正在做的任何事情。

\n


小智 5

getDerivedStateFromProps的存在只是为了使组件能够因 props 的更改而更新其内部状态。由于我们仅根据 props 更新状态,因此没有理由比较 nextProps 和 this.props。这里我们应该只比较下一个 props 和上一个 state,如果 state 和 props 不同,则更新状态,否则不应该更新。

\n\n

如果我们将 this.props 与下一个 props 进行比较,我们需要存储旧的 props 值,这会影响性能。保留过去值的副本称为记忆化。为了避免滥用\xe2\x80\x9cthis\xe2\x80\x9dmemoizationgetDerivedStateFromProps 被设置为static

\n\n

我们也可以将上述视为componentWillReciveProps贬值的原因。

\n