带有 React 的高阶 FRP - 为啥它没有发生?

Posted

技术标签:

【中文标题】带有 React 的高阶 FRP - 为啥它没有发生?【英文标题】:Higher order FRP with React - why is it not happening?带有 React 的高阶 FRP - 为什么它没有发生? 【发布时间】:2017-02-01 14:43:37 【问题描述】:

Redux 是一种一阶 FRP,就像以前的 Elm 一样。

然而,似乎更高阶的 FRP 并没有真正与 react 一起使用。

为什么一阶 FRP 对 React 有用,而高阶 FRP 没那么有用?

也许 React 不需要高阶主义?所以作为回报,一个可以保留时间旅行的调试器?

换句话说:

React 是一个接受状态并返回视图的函数。

FRP 是一种声明和执行状态机的方式。

这些都是正交关注点,那么为什么不将它们结合起来呢?

编辑:

如果我比较这个https://github.com/ochrons/diode/tree/master/examples/todomvc/src/main/scala/example

用这个https://github.com/lihaoyi/workbench-example-app/blob/todomvc/src/main/scala/example/ScalaJSExample.scala

那么,使用 scala.rx 的同一个应用程序的代码行数似乎是使用 Diode 的一半(类似 Redux 的单向数据流库)。

编辑2:

我的猜测 - 为什么它没有发生 - 是大多数高阶 frp 人(他们想在 Web 开发中使用高阶 FRP)使用 reflex-frp,他们使用 reflex-dom 而不是 react。可能 reflex-dom 使反应变得不必要。

【问题讨论】:

即使 ELM(一阶 FRP)也停止 beiig FRP : elm-lang.org/blog/farewell-to-frp ,因为它太难学了。会是这个原因吗?人们只是不喜欢 FRP,因为它不熟悉? 它似乎正在发生,但不是反应而是循环。 可能只是人们害怕FRP?我发现 FRP 非常直观,但是对于某些人来说,通常基于信号的 FRP 公式似乎很难理解。 React 实际上花了一些时间来隐藏它是基于 FRP 的。 好吧,我认为 React 与 FRP 并没有真正的关系。 React 只是一个渲染库,FRP 是一种描述状态机的方式。正交问题。 顺便说一句,React 中子组件在同一位置(在 render() 方法中)渲染和初始化的样式导致了整个 FP 炒作。我编写了简单的包装器,可以使用引用而不是<ChildComponent prop1=val/>。老派的MVC更好。 Redux 的家伙让所有的 FP 炒作变得更加复杂。我们需要架构而不是框架。 【参考方案1】:

编辑:在我看来,我认为 React 和高阶 FRP 概念的一大挑战是 处理 React 组件内部的状态会使用户接触到与 HO FRP 无关的语言概念,在我的意见,我觉得这也是一个更广泛的 ES6 JS 问题。我不是这方面的专家,但我正在分享我在 FRP 旅程中的想法和经验。

React 的很多组件功能和组合都依赖于 JS class 语法。对我来说,这是一个挑战,因为你混淆了术语和概念。对于很多前端开发人员(包括我自己)来说,React 是他们第一次接触 FRP 范式。当您一直在使用 classesconstructors 查看 OOP 继承术语时,很难理解功能组合的重要性。我认为这解释了为什么我们看到了 React 库的这种爆炸式增长,而不是底层范式——因为完全混合了不同的术语。它更多地是关于组件和以 DOM 为中心的视图,而不是 FRP Read this tidy little post。

React 隐藏了很多底层概念,对于许多使用 FRP 范式的程序员来说,他们不喜欢这种神奇的感觉,这意味着新手很容易使用 class 接口来制作他们的组件,而不是接触到很多底层 FRP 范例。

在我看来,在处理状态时,React 本质上应该是只读的。如此对待,React 和 Redux 变得正交。 Redux 更倾向于 FRP 概念,实际上当以这种方式使用时,它变得更具声明性。

const mapStateToProps = (state, ownProps) => 
  return 
    id: ownProps.id,
    someData: state.projects.someData,
  


const mapDispatchToProps = (dispatch) => 
  return 
    onSubmitForm(data)  //our callback
      dispatch( //redux dispatch function
        someAction(data) //our Redux Action Creator
      )
    
  


export default connect(mapStateToProps,mapDispatchToProps)(PresentationComponent)

在我们的展示组件中

const PresentationComponent = (onSubmitForm, id) => 
    return <form id="someForm" onSubmit=(e) => 
        e.preventDefault()
        onSubmitForm(getFormData(id))
    >

通过使用 Redux 的 HO 函数 connect()mapStateToProps()mapDispatchToProps(),它允许使用简单地将状态和方法作为参数接收的纯函数组件。这些方法基本上可以返回任何东西。这当然传达了更高/一阶和 FRP 的更纯粹的概念。

尽管我相信我们会在应用程序和库开发中看到越来越多的 FRP,但我认为我们不要把婴儿和洗澡水一起扔出去也很重要。

在 Dan Abramov 的实用主义 post about Redux 中,他提醒我们,我们不必总是只坚持一种工具并拘泥于一种范式,这并不是说我反对 OOP,我使用工厂和面向对象的概念经常在生产中,我只是觉得使用 OOP 中的术语会有点混乱,然后开始同时谈论 FRP。

值得一看的东西

正如 cmets 中提到的,cycle.js 绝对值得一看。在 React 的声明式和可重用组件结构与 RxJS 中的数据流和可观察对象等概念的好处之间取得了很好的平衡。

这是我的两分钱,我很想听听其他人是否有任何其他意见?

【讨论】:

何是何?高阶什么? “处理 React 组件内部的状态使得 HO 几乎不可能”——这是什么意思? @jhegedus 我已经重写了我的答案,我之前的答案不是特别清楚,希望对您有所帮助?【参考方案2】:

现在正在发生,它是here。我编写了一个超级简单的实验性“网络框架”,它结合了Sodium FRP、React 和 Scala.js。

我喜欢。我写代码,我编译它,它工作。非常实验性的技术,尖端的 FP 东西。这是真正的交易。不妥协 FRP。

【讨论】:

以上是关于带有 React 的高阶 FRP - 为啥它没有发生?的主要内容,如果未能解决你的问题,请参考以下文章

制作一个高阶组件以与 TypeScript 互操作 react-relay 和 react-router

react-redux 项目中的高阶 reducer

TypeScript 和 React:如何重载高阶组件/装饰器?

在 TypeScript 中使用高阶组件在使用时省略 React 属性

为啥我的 javascript 调用回发并且我没有错误?

react:高阶组件wrappedComponent