Skip to main content

保持组件为纯函数组件

JavaScript中有纯函数的概念。纯函数仅仅进行计算。在React中通过将组件编写为纯函数可以避免一些预期之外的行为。为此,我们需要遵守一些规则。

Purity: 组件相当于公式

在计算机科学(尤其是函数式编程领域)中, 纯函数具有以下特征:

  • 它只关心自己的职责。在调用这个函数之前, 它不会修改存在的任何对象或者变量。
  • 相同的输入, 相同的输出。给定相同的输入, 纯函数总是返回相同的结果。

你可能更加熟悉纯函数的一个例子, 就像是数学中的公式。

考虑这个公式: y = 2x

如果 x = 2, 那么 y 一直是 4。 如果 x = 3, 那么 y 一直是 6。

如果我们把这个公式转变为 JavaScript 函数, 它可能是这样:

function double(number) {
return 2 * number;
}

在上面这个例子中, double函数是一个纯函数。如果传入的值是 3, 那么返回值一直为 6。

React 就是围绕这个概念设计的。React 假设你编写的每个组件都是一个纯函数。这意味着在给定相同输入的情况下,编写的 React 组件必须始终返回相同的 JSX

Side Effect: (不)可预期的结果

React 的渲染过程必须始终是的。

一般来说, 我们不应该去关心组件的渲染顺序。y = 2xy = 5x之前调用或者之后调用都没关系。两个公式相互独立运算。同样, 每个组件都应该"只考虑自己", 而不是在渲染过程中与别的组件协调或依赖。

渲染过程就像是学校的考试, 每个组件都应该只计算自己的 JSX。

使用StrictMode检测不纯的计算

在 React 中, 在渲染期间你可以读取到三种输入: props, statecontext。我们总是应该将这些输入当作只读的输入。

当想要更改某些内容以响应用户输入时,应该设置状态而不是写入变量。在渲染组件时,永远不应该更改预先存在的变量或对象。

React 提供了一种“严格模式”,它在开发过程中调用每个组件的函数两次。通过调用函数组件两次,来帮助开发者找到违反这些规则的组件。

可能导致 Side Effect 的行为

尽管函数式编程在很大程度上依赖于纯度, 在某些情况下, 有些东西必须要改变。这些改变, 比如: 更新屏幕, 开启一段动画, 改变数据......都被成为副作用。他们在"另一侧"发生, 并不是在渲染期间执行。

在 React 中, 副作用通常属于事件处理(Event Handlers)。事件处理是 React 在用户执行某些操作的时候运行的函数--例如: 用户点击按钮, 即使在组件内定义了事件处理, 它们也不会在渲染期间执行!所以事件处理是不需要纯度的。

如果已经用尽了所有其他选项并且无法为副作用找到正确的事件处理程序,仍然可以通过 useEffect 在您的组件中调用将它附加到返回的 JSX。这告诉 React 在渲染之后,当允许副作用时执行它。但是,这种方法应该是最后的手段。

为什么 React 关心纯度
  • 纯函数组件可以在不同的环境中运行--例如, 在服务器上!由于它们针对相同的输入返回相同的结果,因此一个组件可以服务于许多用户请求。
  • 可以通过跳过渲染输入没有更改的组件来提高性能。纯函数总是返回相同的结果,因此它们可以安全缓存。
  • 如果在渲染深层组件树的过程中某些数据发生变化, React 可以重新开始渲染,而不会浪费时间来完成过时的渲染。纯度可以确保随时停止计算。