为什么ReasonReact是编写React的最佳方式

3,199 阅读10分钟

原文地址:medium.freecodecamp.org/psst-heres-…

你是否使用 React 来构建用户界面?好吧,我也是。接下来你会了解为什么要使用 ReasonML 来写 React 应用。

React 是构建用户界面的一种很酷的手段,我们该如何让这个过程变得更酷呢?

为了回答这个问题,我们首先要了解 React 作为 JavaScript 库的主要问题是什么?

React 最初并不是为了 JavaScript 而开发的

如果你有深入了解 React,你会发现它的一些主要原则对 JavaScript 来说是陌生的,让我们就 不可变性,函数式编程原则,特别是类型系统来讨论一下这个问题。

  • 不可变性是 React 的核心原则,你肯定不想要改变 props 或者 state,因为你一旦改变了它们,你将面对不可预期的后果。在 JavaScript 中,没有开箱即用的不可变性,我们通过约定保持数据的不可变性,或者使用 immutableJS 这样的库来辅助我们达到目的。
  • React 基于函数式编程的原理,因为 React 应用是函数的组合。尽管 JavaScript 具有一些函数式编程的特性,例如头等函数(是指在程序设计语言中,函数被当作头等公民),但是它并不是一个函数式编程语言。当我们想要写一些优雅的声明式代码的时候,我们还需要像 Lodash/fp 或者 Ramda 的库的辅助。
  • 那么类型系统呢?我们使用React 中的 PropTypes来约定数据类型,因为 JavaScript 本身不是静态类型语言。为了使用强大的静态类型检查,我们仍然还是需要 Flow 和 TypeScript 这样的库来辅助。

如您所见,JavaScript 与 React 的核心原则不兼容。

有没有什么语言比 JavaScript 更适合用来写 React 呢?

幸运的是,我们有 ReasonML。

因为 ReasonML 是基于 OCaml 这样的函数式编程语言,所以 ReasonML 内置了不可变性这样的语言特性,顺理成章地,我们有了开箱即用的不可变性。Reason还为我们提供了一个强大的类型系统。

Reason 兼容了 React 的核心原则。

Reason

Reason 不是一种新语言。它是 OCaml 的另一种类似 JavaScript 的语法和工具链,一种已经存在了20多年的函数式编程语言。Reason是由已经在项目中使用OCaml的Facebook开发人员创建的(Flow,Infer)。

具有类 C 语法的 Reason 使得 OCaml 更容易被 JavaScript或Java等主流语言的用户所接受。 它为您提供了更好的文档(与OCaml相比)和不断增长的社区。 此外,它还可以更轻松地与现有的JavaScript代码库集成。

Reason 语言基于 OCaml 语言,Reason与OCaml具有相同的语义 - 只有语法不同。 这意味着您可以使用Reason的类似JavaScript的语法编写OCaml。 因此,您可以利用OCaml的强大功能,例如强大的类型系统和模式匹配。

我们来看一下Reason的语法示例。

let fizzbuzz = (i) =>
  switch (i mod 3, i mod 5) {
  | (0, 0) => "FizzBuzz"
  | (0, _) => "Fizz"
  | (_, 0) => "Buzz"
  | _ => string_of_int(i)
  };
for (i in 1 to 100) {
  Js.log(fizzbuzz(i))
};

虽然我们在这个例子中使用了模式匹配,但它仍然非常类似于JavaScript,对吧? 但是,浏览器唯一可用的语言仍然是JavaScript,这意味着我们需要编译它。

BuckleScript

Reason的强大功能之一是BuckleScript编译器,它可以获取您的Reason代码,并将其编译为可读且高性能的JavaScript,并消除了极大的代码。如果你在一个不是每个人都熟悉 Reason 的团队工作,你会感激可读性,因为他们仍然能够阅读编译后的 JavaScript 代码。 因为 Reason 与 JavaScript 的有很大的相似性,所以一些 Reason 的代码根本不需要由编译器进行更改。 因此,您可以享受静态类型语言带来的好处,而无需更改任何代码。

let add = (a, b) => a + b;
add(6, 9);

上面这段代码在 Reason 中和 JavaScript 中都有效。

BuckleScript 附带了四个库:名为 Belt 的标准库( OCaml 标准库不足),以及与 JavaScript,Node.js和 DOM API 的绑定。

由于 BuckleScript 基于 OCaml 编译器,因此您将获得比 Babel 快得多的快速编译,并且比 TypeScript 快几倍。

让我们编译我们在Reason中编写的FizzBu​​zz算法。

如您所见,生成的 JavaScript 代码非常易读,就像是由 JavaScript 开发人员编写的。 Reason 不仅编译为 JavaScript,还编译为原生语言和字节码。 因此,您可以使用 Reason 语法编写单个应用程序,并能够在 MacOS,Android 和 iOS 手机上的浏览器中运行它。 Jared Forsyth 有一款叫做 Gravitron 的游戏,它是用 Reason 编写的,它可以在我刚刚提到的所有平台上运行。

JavaScript 互操作

BuckleScript 还为我们提供了 JavaScript 互操作性。 您不仅可以将自己正在运行的 JavaScript 代码粘贴到 Reason 代码库中,还可以将 Reason 代码与该 JavaScript 代码进行交互。 这意味着您可以轻松地将 Reason 代码集成到现有的 JavaScript 代码库中。 此外,您可以在 Reason 代码中使用 NPM 生态系统中的所有 JavaScript 包。 例如,您可以在单个项目中将 Flow,TypeScript 和 Reason 组合在一起。

然而,事情并非那么简单。 要在Reason中使用JavaScript库或代码,您需要首先通过Reason绑定将其移植到Reason。换句话说,您需要类型为您的无类型JavaScript代码,以便能够利用Reason的强类型系统。

每当您需要在Reason代码中使用 JavaScript 库时,请通过浏览 Reason Package Index(Redex)数据库来检查库是否已移植到 Reason。 它是一个网站,它使用 Reason 绑定聚合使用 Reason 和 JavaScript 库编写的不同库和工具。

如果您在那里找到了库,则可以将其作为依赖项安装,并在 Reason 应用程序中使用它。 但是,如果您没有找到您的库,则需要自己编写Reason绑定。 如果您刚开始使用 Reason ,请记住,编写绑定不是您想要开始的事情,因为它是 Reason 生态系统中更具挑战性的事情之一。

幸运的是,我正在写一篇关于编写Reason绑定的帖子,敬请期待! 当您需要JavaScript库中的某些功能时,您不需要为整个库编写Reason绑定。 您只能对需要使用的功能或组件执行此操作。

ReasonReact

本文是关于在 Reason 中的 React,感谢 ReasonReact 库可以做到这一点。

也许你现在在想“我仍然不知道为什么我应该在 Reason 中使用 React。” 我们已经提到过这样做的主要原因 - Reason 比 JavaScript 更兼容 React。

为什么它更兼容?因为 React 是为 Reason 开发的,或者更准确地说是为 OCaml 开发的。

React 的第一个原型是由 Facebook 开发的,用 OCaml 的堂兄标准元语言(StandardML)编写。 然后,它被转移到 OCaml。 React 也被转录为 JavaScript。

这是因为整个网络都在使用 JavaScript,并且说“现在我们将在 OCaml 中构建 UI”并不是很明智。它确实有效--React in JavaScript 已被广泛采用。

因此,我们习惯将 React 用作 JavaScript 库。React 与其他库和语言 - Elm,Redux,Recompose,Ramda和PureScript - 在JavaScript中流行的函数式编程。 随着Flow和TypeScript的兴起,静态类型也变得流行。 因此,具有静态类型的函数式编程范式成为前端世界的主流。

2016年,Bloomberg开发并开源了BuckleScript,这是一种将OCaml转换为JavaScript的编译器。

这使他们能够使用OCaml的强类型系统在前端编写安全代码。 他们采用优化且极其快速的OCaml编译器并交换其后端生成本机代码,用于生成JavaScript。

函数式编程的普及以及BuckleScript的发布为Facebook提供了理想的环境,使其能够回到最初以ML语言编写的React的最初想法。

他们采用了OCaml语义和JavaScript语法,并创建了Reason。 他们还在React - ReasonReact库周围创建了Reason包装器,并具有其他功能,例如在有状态组件中封装Redux原则。 通过这样做,他们将React归还其原始根源。

React in Reason的能量

当React进入JavaScript时,我们通过引入各种库和工具来调整JavaScript以满足React的需求。

这也意味着我们项目的依赖性更高。 更不用说这些库仍处于开发阶段,并定期引入重大变化。 因此,您需要在项目中谨慎维护这些依赖关系。 这为JavaScript开发增加了另一层复杂性。 您典型的React应用程序至少具有以下依赖项:

  • 静态类型 - Flow / TypeScript
  • 不变性 - immutableJS
  • 路由 - ReactRouter
  • 格式 - Prettier
  • linting - ESLint
  • 辅助功能 - Ramda / Lodash

现在让我们用 ReasonReact 来替代 JavaScript React。 我们还需要所有这些依赖吗?

  • 静态类型 - 内置
  • 不变性 - 内置
  • 路由 - 内置
  • 格式 - 内置
  • linting - 内置
  • 辅助功能 - 内置

您可以在我的其他帖子中了解有关这些内置功能的更多信息。

在ReasonReact应用程序中,您不需要这些和许多其他依赖项,因为许多使您的开发更容易的关键功能已包含在语言本身中。 因此,维护您的软件包将变得更加容易,并且您不会随着时间的推移而增加复杂性。 这要归功于已有20多年历史的OCaml。 它是一种成熟的语言,其所有核心原则都已到位且稳定。

Wrap-up

起初,Reason的创造者有两种选择。 采用JavaScript并以某种方式使其更好。 通过这样做,他们还需要处理其历史负担。 但是,他们采取了不同的方式。 他们将OCaml作为一种成熟的语言,具有出色的性能并对其进行了修改,使其类似于JavaScript。 React也基于OCaml的原理。 这就是为什么当你在Reason中使用它时,你将获得更好的开发者体验。 React in Reason代表了构建React组件的更安全的方式,因为强类型系统已经得到了回应,您不需要处理大多数JavaScript(遗留)问题。

What’s next?

如果您来自JavaScript世界,由于其与JavaScript的语法相似性,您可以更轻松地开始使用Reason。

如果你一直在React中编程,那么你会更容易,因为你可以使用你所有的React知识,因为ReasonReact具有与React相同的心理模型和非常相似的工作流程。

这意味着您无需从头开始。

随着您的发展,您将学习理性。

在项目中开始使用Reason的最佳方法是逐步进行。

我已经提到你可以使用Reason代码并在JavaScript中使用它,反之亦然。

您可以使用ReasonReact执行相同的操作。 您可以使用ReasonReact组件并在React JavaScript应用程序中使用它,反之亦然。

这种增量方法已被Facebook开发人员选择,他们在开发Facebook Messenger应用程序时广泛使用Reason。

如果你想使用React in Reason构建一个应用程序并以实用的方式学习Reason的基础知识,请查看我的其他文章,我们将在一起构建一个Tic Tac Toe游戏。

如果您有任何问题,批评,观察或改进提示,请随时在下面写评论或通过Twitter或我的博客与我联系。