首页 文章

为什么在Facebook Flux上使用Redux?

提问于
浏览
1064

我读过this answerreducing boilerplate,看了几个GitHub的例子,甚至试了一下redux(todo apps) .

据我了解,official redux doc motivations提供了与传统MVC架构相比的优点 . 但它没有提供问题的答案:

Why you should use Redux over Facebook Flux?

这只是编程风格的问题:功能与非功能?或者问题是在redux方法中遵循的能力/开发工具?也许缩放?还是测试?

如果我说redux对于来自函数式语言的人来说是一种变化,我是对的吗?

To answer this question you may compare the complexity of implementation redux's motivation points on flux vs redux.

以下是official redux doc motivations的动机要点:

  • 处理乐观更新(据我所知,它几乎不取决于第5点 . 难道在facebook flux中实现它吗?)

  • 在服务器上渲染(facebook flux也可以这样做 . 与redux相比有什么好处?)

  • 在执行路由转换之前获取数据(为什么它可以't be achieved in facebook flux? What'的好处?)

  • 热重装(这可能是React Hot Reload . 为什么我们需要redux?)

  • 撤消/重做功能

  • 其他什么点?像坚持国家一样......

8 回答

  • 24

    以下是Redux over Flux的简单解释 . Redux没有调度程序 . 它依赖于名为reducers的纯函数 . 它不需要调度员 . 每个操作由一个或多个Reducer处理以更新单个存储 . 由于数据是不可变的,因此reducers返回更新存储的新更新状态

    有关更多信息http://www.prathapkudupublog.com/2017/04/flux-vs-redux.html

  • 2

    我是早期采用者,使用Facebook Flux库实现了一个中大型单页面应用程序 .

    由于我的谈话有点迟,我只想指出,尽管我最好的希望Facebook似乎认为他们的Flux实施是一个概念证明,它从未得到应有的关注 .

    我鼓励你玩它,因为它暴露了Flux架构的更多内部工作,这是非常有教育意义,但同时它没有提供像Redux这样的库提供的许多好处(它们不是这对小型项目很重要,但对大型项目非常有 Value ) .

    我们决定继续前进,我们将转向Redux,我建议你这样做;)

  • 52

    Redux作者在这里!

    Redux与Flux没有什么不同 . 总体而言,它具有相同的架构,但Redux能够通过使用Flux使用回调注册的功能组合来削减一些复杂角落 .

    Redux没有根本的区别,但是我发现它使得某些抽象更容易,或者至少可以实现,这在Flux中很难或不可能实现 .

    减速剂成分

    以分页为例 . 我的Flux + React Router example处理分页,但代码很糟糕 . 可怕的原因之一是 Flux makes it unnatural to reuse functionality across stores. 如果两个商店需要处理分页以响应不同的操作,他们要么需要从公共基础商店继承(糟糕!你是私有状态 . 整个事情是混乱的(虽然肯定在可能的领域) .

    另一方面,由于减速器的成分,Redux的分页很自然 . 它一直是减速器,所以你可以写一个reducer factory that generates pagination reducers然后use it in your reducer tree . 这么简单的关键因为 in Flux, stores are flat, but in Redux, reducers can be nested via functional composition, just like React components can be nested.

    这种模式还可以实现非用户代码undo/redo等精彩功能 . Can you imagine plugging Undo/Redo into a Flux app being two lines of code? Hardly. With Redux, it is -感谢减速器组成模式 . 我需要强调的是,它并没有什么新鲜事 - 这是在_153179中开创并详细描述的模式,它本身受到Flux的影响 .

    服务器渲染

    人们使用Flux在服务器上渲染得很好,但是看到我们有20个Flux库,每个都试图让服务器呈现“更容易”,也许Flux在服务器上有一些粗糙的边缘 . 事实是Facebook没有做太多的服务器渲染,因此他们并没有非常关注它,而是依靠生态系统来简化它 .

    在传统的Flux中,商店是单身人士 . 这意味着很难为服务器上的不同请求分离数据 . 不是不可能,但很难 . 这就是为什么大多数Flux库(以及新的Flux Utils)现在建议您使用类而不是单例,因此您可以为每个请求实例化存储 .

    您需要在Flux中解决以下问题(您自己或在您喜欢的Flux库的帮助下,例如FlummoxAlt):

    • 如果商店是类,我如何使用每个请求的调度程序创建和销毁它们?我什么时候注册商店?

    • 如何保存商店中的数据,然后在客户端进行补水?我需要为此实现特殊方法吗?

    诚然,Flux框架(不是vanilla Flux)可以解决这些问题,但我发现它们过于复杂 . 例如,Flummox asks you to implement serialize() and deserialize() in your stores . Alt通过提供takeSnapshot()来自动序列化JSON树中的状态,从而解决了这个问题 .

    Redux更进一步: since there is just a single store (managed by many reducers), you don't need any special API to manage the (re)hydration. 你只是一个商店,你可以读取其当前状态,或创建具有新状态的新商店 . 每个请求都有一个单独的商店实例 . Read more about server rendering with Redux.

    同样,这是一个可能在Flux和Redux中都有可能的情况,但是Flux库通过引入大量的API和约定来解决这个问题,而Redux甚至不需要解决它,因为它没有解决这个问题 . 首先归功于概念简洁性 .

    开发人员体验

    我实际上并不打算让Redux成为一个受欢迎的Flux库 - 我在写作ReactEurope talk on hot reloading with time travel时写了它 . 我有一个主要目标: make it possible to change reducer code on the fly or even “change the past” by crossing out actions, and see the state being recalculated.

    我还没有看到一个能够做到这一点的Flux库 . React Hot Loader也不允许你这样做 - 事实上,如果你编辑Flux商店它会中断,因为它不知道如何处理它们 .

    当Redux需要重新加载reducer代码时,它会调用replaceReducer(),并且应用程序将使用新代码运行 . 在Flux中,数据和函数纠缠在Flux存储中,因此您必须以某种方式使用Dispatcher重新注册新版本 - Redux甚至没有 .

    生态系统

    Redux有rich and fast-growing ecosystem . 这是因为它提供了一些扩展点,例如middleware . 它的设计考虑了logging,支持PromisesObservablesroutingimmutability dev checkspersistence等用例 . 并非所有这些都会变得有用,但很高兴能够访问一组可以轻松组合在一起工作的工具 .

    简洁

    Redux保留了Flux的所有优点(记录和重放动作,单向数据流,依赖变异),并增加了新的好处(轻松撤消 - 重做,热重新加载),而无需引入Dispatcher和商店注册 .

    保持简单很重要,因为它可以在您实现更高级别的抽象时保持理智 .

    与大多数Flux库不同,Redux API表面很小 . 如果删除开发人员警告,注释和完整性检查,则为99 lines . 调试没有棘手的异步代码 .

    您实际上可以阅读它并了解Redux的所有内容 .


    另见my answer on downsides of using Redux compared to Flux .

  • 16

    我在Flux工作了很长时间,现在使用Redux已经很长时间了 . 正如丹指出的那样,两种架构都没有那么不同 . 事情是,Redux使事情更简单,更清洁 . 它会在Flux上教你一些东西 . 例如,Flux是单向数据流的完美示例 . 我们将数据,操作和视图层分开的问题分离 . 在Redux中我们有相同的东西,但我们也学习了不变性和纯函数 .

  • 1887

    In Quora, somebody says:

    首先,完全可以使用React编写应用程序而不使用Flux .

    也是这个 visual diagram ,我想阅读整个解释:

    但如果您仍然对更多信息感兴趣,请继续阅读 .

    我相信你应该从纯粹的React开始,然后学习Redux和Flux . 在您对React有一些实际经验之后,您将看到Redux是否对您有所帮助 . 也许你会觉得Redux完全适合你的应用程序,也许你会发现,Redux正试图解决你并没有真正遇到的问题 . 如果你直接使用Redux,你可能会得到过度设计的代码,代码更难以维护,甚至更多的错误,而不是没有Redux .

    Redux docs

    动机随着JavaScript单页面应用程序的要求变得越来越复杂,我们的代码必须管理比以往更多的状态 . 此状态可以包括服务器响应和缓存数据,以及尚未持久保存到服务器的本地创建的数据 . UI状态的复杂性也在增加,因为我们需要管理活动路由,选定的选项卡,微调器,分页控件等 . 管理这个不断变化的状态很难 . 如果模型可以更新另一个模型,那么视图可以更新模型,该模型会更新另一个模型,而这反过来可能会导致另一个视图更新 . 在某些时候,您不再理解您的应用中发生了什么,因为您已经失去了对其状态的时间,原因和方式的控制 . 当系统不透明且不确定时,很难重现错误或添加新功能 . 好像这还不够糟糕,考虑新要求在前端产品开发中变得普遍 . 作为开发人员,我们期望处理乐观更新,服务器端呈现,在执行路由转换之前获取数据等等 . 我们发现自己试图管理以前从未处理过的复杂性,我们不可避免地提出这样一个问题:是时候放弃了吗?答案是否定的 . 这种复杂性很难处理,因为我们混合了人类思维难以理解的两个概念:变异和异步性 . 我称他们为Mentos和Coke . 两者在分离时都很棒,但是它们一起造成了混乱 . 像React这样的库试图通过删除异步和直接DOM操作来解决视图层中的这个问题 . 然而,管理您的数据状态由您自己决定 . 这就是Redux的用武之地 . 在Flux,CQRS和Event Sourcing的脚步之后,Redux试图通过对更新发生的方式和时间施加某些限制来使状态变异可预测 . 这些限制反映在Redux的三个原则中 .

    同样来自Redux docs

    核心概念Redux本身非常简单 . 想象一下,您的应用程序的状态被描述为一个普通对象 . 例如,todo应用程序的状态可能如下所示:{
    待办事项:[{
    文字:'吃的食物',
    完成:是的
    },{
    文字:'练习',
    完成:假
    }],
    visibilityFilter:'SHOW_COMPLETED'
    }
    这个对象就像一个“模型”,除了没有setter . 这样代码的不同部分不能任意改变状态,导致难以重现的错误 . 要更改状态中的某些内容,您需要发送操作 . 一个动作是一个简单的JavaScript对象(请注意我们如何不引入任何魔法?),它描述了发生的事情 . 以下是一些示例操作:{type:'ADD_TODO',text:'Go to swimming pool'}
    {type:'TOGGLE_TODO',索引:1}
    {type:'SET_VISIBILITY_FILTER',过滤器:'SHOW_ALL'}
    强制将每个更改描述为一个操作,让我们清楚地了解应用程序中发生的情况 . 如果发生了变化,我们就知道它为什么会改变行动就像发生了什么的面包屑 . 最后,为了将状态和动作联系在一起,我们编写了一个名为reducer的函数 . 再一次,没有什么神奇之处 - 它只是一个将状态和动作作为参数的函数,并返回应用程序的下一个状态 . 为大型应用程序编写这样的函数会很困难,因此我们编写管理状态部分的较小函数:function visibilityFilter(state ='SHOW_ALL',action){
    if(action.type ==='SET_VISIBILITY_FILTER'){
    return action.filter;
    } else {
    返回状态;
    }
    }

    function todos(state = [],action){
    switch(action.type){
    案例'ADD_TODO':
    return state.concat([{text:action.text,completed:false}]);
    案例'TOGGLE_TODO':
    return state.map((todo,index)=>
    action.index === index?
    {text:todo.text,completed:!todo.completed}:
    去做

    默认:
    返回状态;
    }
    }
    我们编写另一个reducer来管理应用程序的完整状态,方法是调用相应状态键的两个reducers:function todoApp(state = {},action){
    返回{
    todos:todos(state.todos,action),
    visibilityFilter:visibilityFilter(state.visibilityFilter,action)
    };
    }
    这基本上是Redux的整个想法 . 请注意,我们没有使用任何Redux API . 它附带了一些实用程序来实现这种模式,但主要的想法是描述状态如何随着时间的推移而更新以响应操作对象,并且您编写的90%的代码只是简单的JavaScript,没有使用Redux本身,它的API,或任何魔术 .

  • 84

    你可能最好开始阅读Dan Abramov的这篇文章,他在撰写redux时讨论了Flux的各种实现及其权衡:The Evolution of Flux Frameworks

    其次,你链接的动机页面并没有真正讨论Redux的动机,而是Flux(和React)背后的动机 . Three Principles更具特定于Redux,但仍然没有处理与标准Flux架构的实现差异 .

    基本上,Flux有多个商店,可以响应UI / API与组件的交互来计算状态变化,并将这些变化作为组件可以订阅的事件进行广播 . 在Redux中,每个组件只有一个商店订阅 . IMO感觉至少像Redux通过统一(或减少,如Redux所说)数据流回到组件来进一步简化和统一数据流 - 而Flux专注于统一数据流的另一端 - 查看到模型 .

  • 4

    除了前面答案中描述的技术论点,恕我直言的两个重要原因是:

    • 工具:Redux开发工具是一个很棒的工具,让您的开发人员/调试体验充满活力(时间机器,导出用户会话并在本地环境中重放它的能力......) .

    • 堆栈溢出友好:Redux在stackoverflow上获得超过51000个结果,通量9000 .

  • 0

    来自2018年中期从(几年)ExtJS迁移的新的react / redux采用者:

    在向下滑动redux学习曲线后,我有同样的问题,并认为纯通量会像OP一样简单 .

    我很快就看到了如上面的答案中所提到的还原剂的优势,并且正在将其应用到我的第一个应用程序中 .

    在再次 grab 锅炉板的同时,我尝试了一些其他的状态管理库,我找到的最好的是rematch .

    它比香草还原更直观,它削减了90%的样板,减少了我花在redux上的75%(我认为库应该做的事情),我能够得到几个企业应用程序马上去 .

    它也使用相同的redux工具运行 . 这是good article这涵盖了一些好处 .

    因此,对于那些到达此SO帖子搜索“更简单的redux”的人,我建议尝试将其作为redux的一个简单替代方案,具有所有优点和四分之一的样板 .

相关问题