为什么使用Redux而不是Facebook Flux? [关闭]

本文翻译自:Why use Redux over Facebook Flux? [closed]

I've read this answer , reducing boilerplate , looked at few GitHub examples and even tried redux a little bit (todo apps). 我已经阅读了这个答案减少了样板 ,看了几个GitHub示例,甚至尝试了redux(todo apps)。

As I understand, official redux doc motivations provide pros comparing to traditional MVC architectures. 据我了解, 官方redux doc动机提供了与传统MVC架构相比的优点。 BUT it doesn't provide an answer to the question: 但它没有提供问题的答案:

Why you should use Redux over Facebook Flux? 为什么你应该使用Redux而不是Facebook Flux?

Is that only a question of programming styles: functional vs non-functional? 这只是编程风格的问题:功能与非功能? Or the question is in abilities/dev-tools that follow from redux approach? 或者问题是在redux方法中遵循的能力/开发工具? Maybe scaling? 也许缩放? Or testing? 还是测试?

Am I right if I say that redux is a flux for people who come from functional languages? 如果我说redux对于来自函数式语言的人来说是一种变化,我是对的吗?

To answer this question you may compare the complexity of implementation redux's motivation points on flux vs redux. 要回答这个问题,您可以比较实施redux在flux和redux上的动机点的复杂性。

Here are motivation points from official redux doc motivations : 以下是官方redux doc动机的动机点:

  1. Handling optimistic updates ( as I understand, it hardly depends on 5th point. Is it hard to implement it in facebook flux? ) 处理乐观的更新( 据我所知,它几乎不取决于第5点。难道在facebook flux中实现它吗?
  2. Rendering on the server ( facebook flux also can do this. Any benefits comparing to redux? ) 在服务器上渲染( facebook flux也可以做到这一点。与redux相比有什么好处?
  3. Fetching data before performing route transitions ( Why it can't be achieved in facebook flux? What's the benefits? ) 在执行路由转换之前获取数据( 为什么在facebook中无法实现?有什么好处?
  4. Hot reload ( It's possible with React Hot Reload . Why do we need redux? ) 热重载( 可以使用React Hot Reload 。为什么我们需要redux?
  5. Undo/Redo functionality 撤消/重做功能
  6. Any other points? 还有其他一点吗? Like persisting state... 像坚持国家一样......

#1楼

参考:https://stackoom.com/question/2CCeD/为什么使用Redux而不是Facebook-Flux-关闭


#2楼

You might be best starting with reading this post by Dan Abramov where he discusses various implementations of Flux and their trade-offs at the time he was writing redux: The Evolution of Flux Frameworks 你可能最好开始阅读Dan Abramov的这篇文章,他在撰写redux时讨论了Flux的各种实现及其权衡: Flux框架的演变

Secondly that motivations page you link to does not really discuss the motivations of Redux so much as the motivations behind Flux (and React). 其次,你链接的动机页面并没有真正讨论Redux的动机,而是Flux(和React)背后的动机。 The Three Principles is more Redux specific though still does not deal with the implementation differences from the standard Flux architecture. 三原则更具特定于Redux,但仍然没有处理与标准Flux架构的实现差异。

Basically, Flux has multiple stores that compute state change in response to UI/API interactions with components and broadcast these changes as events that components can subscribe to. 基本上,Flux有多个商店,可以响应UI / API与组件的交互来计算状态变化,并将这些更改作为组件可以订阅的事件进行广播。 In Redux, there is only one store that every component subscribes to. 在Redux中,每个组件只有一个商店订阅。 IMO it feels at least like Redux further simplifies and unifies the flow of data by unifying (or reducing, as Redux would say) the flow of data back to the components - whereas Flux concentrates on unifying the other side of the data flow - view to model. IMO感觉至少像Redux通过统一(或减少,如Redux所说)数据流回到组件来进一步简化和统一数据流 - 而Flux专注于统一数据流的另一面 - 查看到模型。


#3楼

Redux author here! Redux的作者在这里!

Redux is not that different from Flux. Redux与Flux没有什么不同。 Overall it has same architecture, but Redux is able to cut some complexity corners by using functional composition where Flux uses callback registration. 总体而言,它具有相同的架构,但Redux能够通过使用Flux使用回调注册的功能组合来削减一些复杂角落。

There is not a fundamental difference in Redux, but I find it makes certain abstractions easier, or at least possible to implement, that would be hard or impossible to implement in Flux. Redux没有根本的区别,但我发现它使得某些抽象更容易,或者至少可以实现,这在Flux中很难或不可能实现。

Reducer Composition 减速剂成分

Take, for example, pagination. 以分页为例。 My Flux + React Router example handles pagination, but the code for that is awful. My Flux + React Router示例处理分页,但代码很糟糕。 One of the reasons it's awful is that Flux makes it unnatural to reuse functionality across stores. 可怕的原因之一是Flux使得跨商店重用功能变得不自然。 If two stores need to handle pagination in response to different actions, they either need to inherit from a common base store (bad! you're locking yourself into a particular design when you use inheritance), or call an externally defined function from within the event handler, which will need to somehow operate on the Flux store's private state. 如果两个商店需要处理分页以响应不同的操作,它们或者需要从公共基本存储继承(糟糕!当您使用继承时将自己锁定到特定设计中),或者从内部调用外部定义的函数事件处理程序,需要以某种方式操作Flux存储的私有状态。 The whole thing is messy (although definitely in the realm of possible). 整件事情很混乱(虽然绝对是可能的)。

On the other hand, with Redux pagination is natural thanks to reducer composition. 另一方面,由于减速器的成分,Redux的分页很自然。 It's reducers all the way down, so you can write a reducer factory that generates pagination reducers and then use it in your reducer tree . 它一直是减速器,因此您可以编写一个减速器工厂来生成分页减速器 ,然后在减速器树中使用它 The key to why it's so easy is because in Flux, stores are flat, but in Redux, reducers can be nested via functional composition, just like React components can be nested. 这么简单的关键是因为在Flux中,商店是平的,但在Redux中,reducers可以通过功能组合嵌套,就像React组件可以嵌套一样。

This pattern also enables wonderful features like no-user-code undo/redo . 此模式还支持非用户代码撤消/重做等精彩功能。 Can you imagine plugging Undo/Redo into a Flux app being two lines of code? 你能想象将Undo / Redo插入一个两行代码的Flux应用程序吗? Hardly. 几乎不。 With Redux, it is —again, thanks to reducer composition pattern. 使用Redux,由于减速器组成模式,它是重要的 I need to highlight there's nothing new about it—this is the pattern pioneered and described in detail in Elm Architecture which was itself influenced by Flux. 我需要强调的是,没有什么新鲜事 - 这是Elm Architecture中开创并详细描述的模式,它本身受到Flux的影响。

Server Rendering 服务器渲染

People have been rendering on the server fine with Flux, but seeing that we have 20 Flux libraries each attempting to make server rendering “easier”, perhaps Flux has some rough edges on the server. 人们使用Flux在服务器上渲染得很好,但是看到我们有20个Flux库,每个都试图让服务器呈现“更容易”,也许Flux在服务器上有一些粗糙的边缘。 The truth is Facebook doesn't do much server rendering, so they haven't been very concerned about it, and rely on the ecosystem to make it easier. 事实是Facebook没有做太多的服务器渲染,所以他们并没有非常关注它,并依靠生态系统来使它更容易。

In traditional Flux, stores are singletons. 在传统的Flux中,商店是单身人士。 This means it's hard to separate the data for different requests on the server. 这意味着很难为服务器上的不同请求分离数据。 Not impossible, but hard. 不是不可能,但很难。 This is why most Flux libraries (as well as the new Flux Utils ) now suggest you use classes instead of singletons, so you can instantiate stores per request. 这就是为什么大多数Flux库(以及新的Flux Utils )现在建议您使用类而不是单例,因此您可以按请求实例化存储。

There are still the following problems that you need to solve in Flux (either yourself or with the help of your favorite Flux library such as Flummox or Alt ): 您仍需要在Flux中解决以下问题(您自己或在您喜欢的Flux库(如FlummoxAlt )的帮助下):

  • If stores are classes, how do I create and destroy them with dispatcher per request? 如果商店是类,我如何使用每个请求的调度程序创建和销毁它们? When do I register stores? 我什么时候注册商店?
  • How do I hydrate the data from the stores and later rehydrate it on the client? 如何保存商店中的数据,然后在客户端上重新水合? Do I need to implement special methods for this? 我需要为此实现特殊方法吗?

Admittedly Flux frameworks (not vanilla Flux) have solutions to these problems, but I find them overcomplicated. 不可否认,Flux框架(不是vanilla Flux)可以解决这些问题,但我发现它们过于复杂。 For example, Flummox asks you to implement serialize() and deserialize() in your stores . 例如, Flummox要求您在商店中实现serialize()和deserialize deserialize() Alt solves this nicer by providing takeSnapshot() that automatically serializes your state in a JSON tree. Alt通过提供takeSnapshot()自动序列化JSON树中的状态来解决这个问题。

Redux just goes further: since there is just a single store (managed by many reducers), you don't need any special API to manage the (re)hydration. Redux更进一步: 因为只有一个商店(由许多减速器管理),你不需要任何特殊的API来管理(重新)水合作用。 You don't need to “flush” or “hydrate” stores—there's just a single store, and you can read its current state, or create a new store with a new state. 您不需要“刷新”或“保湿”商店 - 只有一个商店,您可以读取其当前状态,或创建具有新状态的新商店。 Each request gets a separate store instance. 每个请求都有一个单独的商店实例。 Read more about server rendering with Redux. 阅读有关Redux服务器渲染的更多信息。

Again, this is a case of something possible both in Flux and Redux, but Flux libraries solve this problem by introducing a ton of API and conventions, and Redux doesn't even have to solve it because it doesn't have that problem in the first place thanks to conceptual simplicity. 同样,这是Flux和Redux中可能存在的一种情况,但是Flux库通过引入大量API和约定来解决这个问题,而Redux甚至不必解决它,因为它没有解决这个问题。第一名归功于概念简洁。

Developer Experience 开发经验

I didn't actually intend Redux to become a popular Flux library—I wrote it as I was working on my ReactEurope talk on hot reloading with time travel . 我实际上并没有打算让Redux成为一个受欢迎的Flux库 - 我写的是因为我正在研究ReactEurope关于时间旅行热重载的讨论 I had one main objective: 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. 我有一个主要目标: 可以动态更改减速器代码,甚至可以通过交叉操作“改变过去”,并查看重新计算的状态。

I haven't seen a single Flux library that is able to do this. 我还没有看到一个能够做到这一点的Flux库。 React Hot Loader also doesn't let you do this—in fact it breaks if you edit Flux stores because it doesn't know what to do with them. React Hot Loader也不允许你这样做 - 事实上,如果你编辑Flux商店它会中断,因为它不知道如何处理它们。

When Redux needs to reload the reducer code, it calls replaceReducer() , and the app runs with the new code. 当Redux需要重新加载reducer代码时,它会调用replaceReducer() ,并且应用程序将使用新代码运行。 In Flux, data and functions are entangled in Flux stores, so you can't “just replace the functions”. 在Flux中,数据和功能纠缠在Flux存储中,因此您不能“只更换功能”。 Moreover, you'd have to somehow re-register the new versions with the Dispatcher—something Redux doesn't even have. 此外,您必须以某种方式使用Dispatcher重新注册新版本 - Redux甚至没有。

Ecosystem 生态系统

Redux has a rich and fast-growing ecosystem . Redux拥有丰富且快速发展的生态系统 This is because it provides a few extension points such as middleware . 这是因为它提供了一些扩展点,如中间件 It was designed with use cases such as logging , support for Promises , Observables , routing , immutability dev checks , persistence , etc, in mind. 它的设计考虑了日志 ,支持PromisesObservables路由immutability dev检查持久性等用例。 Not all of these will turn out to be useful, but it's nice to have access to a set of tools that can be easily combined to work together. 并非所有这些都会变得有用,但很高兴能够访问一组可以轻松组合在一起工作的工具。

Simplicity 简单

Redux preserves all the benefits of Flux (recording and replaying of actions, unidirectional data flow, dependent mutations) and adds new benefits (easy undo-redo, hot reloading) without introducing Dispatcher and store registration. Redux保留了Flux的所有优点(记录和重放动作,单向数据流,依赖变异)并增加了新的好处(简单的撤销重做,热重新加载),而不引入Dispatcher和商店注册。

Keeping it simple is important because it keeps you sane while you implement higher-level abstractions. 保持简单很重要,因为它可以在您实现更高级别的抽象时保持理智。

Unlike most Flux libraries, Redux API surface is tiny. 与大多数Flux库不同,Redux API表面很小。 If you remove the developer warnings, comments, and sanity checks, it's 99 lines . 如果删除开发人员警告,注释和完整性检查,则为99行 There is no tricky async code to debug. 调试没有棘手的异步代码。

You can actually read it and understand all of Redux. 您实际上可以阅读它并了解Redux的所有内容。


See also my answer on downsides of using Redux compared to Flux . 另请参阅我对使用Redux与Flux相比的缺点的答案


#4楼

I'm an early adopter and implemented a mid-large single page application using the Facebook Flux library. 我是早期采用者,使用Facebook Flux库实现了一个中大型单页面应用程序。

As I'm a little late to the conversation I'll just point out that despite my best hopes Facebook seem to consider their Flux implementation to be a proof of concept and it has never received the attention it deserves. 由于我对谈话有点迟,我只想指出,尽管我最好的希望Facebook似乎认为他们的Flux实现是一个概念证明,它从未得到应有的关注。

I'd encourage you to play with it, as it exposes more of the inner working of the Flux architecture which is quite educational, but at the same time it does not provide many of the benefits that libraries like Redux provide (which aren't that important for small projects, but become very valuable for bigger ones). 我鼓励你玩它,因为它暴露了Flux架构的更多内部工作,这是非常有教育意义,但同时它没有提供像Redux这样的库提供的许​​多好处(它们不是这对小型项目很重要,但对大型项目非常有价值)。

We have decided that moving forward we will be moving to Redux and I suggest you do the same ;) 我们决定继续前进,我们将转向Redux,我建议你这样做;)


#5楼

In Quora, somebody says : 在Quora,有人说

First of all, it is totally possible to write apps with React without Flux. 首先,完全可以使用React编写应用程序而不使用Flux。

Also this visual diagram which I've created to show a quick view of both, probably a quick answer for the people who don't want to read the whole explanation: 另外,我创建的这个视觉图表显示了两者的快速视图,对于不想阅读整个解释的人来说可能是一个快速的答案: Flux vs Redux

But if you still interested knowing more, read on. 但如果您仍然对更多信息感兴趣,请继续阅读。

I believe you should start with pure React, then learn Redux and Flux. 我相信你应该从纯粹的React开始,然后学习Redux和Flux。 After you will have some REAL experience with React, you will see whether Redux is helpful for you or not. 在您对React有一些实际经验之后,您将看到Redux是否对您有所帮助。

Maybe you will feel that Redux is exactly for your app and maybe you will find out, that Redux is trying to solve a problem you are not really experiencing. 也许你会觉得Redux完全适合你的应用程序,也许你会发现,Redux正试图解决你并没有真正遇到的问题。

If you start directly with Redux, you may end up with over-engineered code, code harder to maintain and with even more bugs and than without Redux. 如果你直接使用Redux,你最终可能会得到过度设计的代码,代码难以维护,甚至更多的错误,而不是没有Redux。

From Redux docs : 来自Redux文档

Motivation 动机
As the requirements for JavaScript single-page applications have become increasingly complicated, our code must manage more state than ever before. 随着JavaScript单页面应用程序的要求变得越来越复杂,我们的代码必须管理比以往更多的状态。 This state can include server responses and cached data, as well as locally created data that has not yet been persisted to the server. 此状态可以包括服务器响应和缓存数据,以及尚未持久保存到服务器的本地创建的数据。 UI state is also increasing in complexity, as we need to manage active routes, selected tabs, spinners, pagination controls, and so on. UI状态的复杂性也在增加,因为我们需要管理活动路径,选定选项卡,微调器,分页控件等。

Managing this ever-changing state is hard. 管理这个不断变化的状态很难。 If a model can update another model, then a view can update a model, which updates another model, and this, in turn, might cause another view to update. 如果模型可以更新另一个模型,则视图可以更新模型,该模型会更新另一个模型,而这反过来可能会导致另一个视图更新。 At some point, you no longer understand what happens in your app as you have lost control over the when, why, and how of its state. 在某些时候,您不再理解您的应用中发生了什么,因为您已经失去了对其状态的时间,原因和方式的控制。 When a system is opaque and non-deterministic, it's hard to reproduce bugs or add new features. 当系统不透明且不确定时,很难重现错误或添加新功能。

As if this wasn't bad enough, consider the new requirements becoming common in front-end product development. 好像这还不够糟糕,考虑新要求在前端产品开发中变得普遍。 As developers, we are expected to handle optimistic updates, server-side rendering, fetching data before performing route transitions, and so on. 作为开发人员,我们期望处理乐观更新,服务器端呈现,在执行路由转换之前获取数据等等。 We find ourselves trying to manage a complexity that we have never had to deal with before, and we inevitably ask the question: Is it time to give up? 我们发现自己试图管理以前从未处理过的复杂性,我们不可避免地提出这样一个问题:是时候放弃了吗? The answer is No. 答案是不。

This complexity is difficult to handle as we're mixing two concepts that are very hard for the human mind to reason about: mutation and asynchronicity. 这种复杂性很难处理,因为我们混合了人类思维难以推理的两个概念:变异和异步性。 I call them Mentos and Coke. 我称他们为Mentos和Coke。 Both can be great when separated, but together they create a mess. 两者在分离时都很棒,但它们一起造成混乱。 Libraries like React attempt to solve this problem in the view layer by removing both asynchrony and direct DOM manipulation. 像React这样的库试图通过删除异步和直接DOM操作来解决视图层中的这个问题。 However, managing the state of your data is left up to you. 但是,管理数据状态取决于您。 This is where Redux comes in. 这是Redux的用武之地。

Following in the footsteps of Flux, CQRS, and Event Sourcing, Redux attempts to make state mutations predictable by imposing certain restrictions on how and when updates can happen. 跟随Flux,CQRS和Event Sourcing的脚步,Redux试图通过对更新发生的方式和时间施加某些限制来使状态变异可预测。 These restrictions are reflected in the three principles of Redux. 这些限制反映在Redux的三个原则中。

Also from Redux docs : 也来自Redux docs

Core Concepts 核心概念
Redux itself is very simple. Redux本身很简单。

Imagine your app's state is described as a plain object. 想象一下,您的应用程序的状态被描述为一个普通对象。 For example, the state of a todo app might look like this: 例如,todo应用程序的状态可能如下所示:

 { todos: [{ text: 'Eat food', completed: true }, { text: 'Exercise', completed: false }], visibilityFilter: 'SHOW_COMPLETED' } 

This object is like a "model" except that there are no setters. 这个对象就像一个“模型”,除了没有setter。 This is so that different parts of the code can't change the state arbitrarily, causing hard-to-reproduce bugs. 这样代码的不同部分不能任意改变状态,导致难以重现的错误。

To change something in the state, you need to dispatch an action. 要更改状态中的某些内容,您需要发送操作。 An action is a plain JavaScript object (notice how we don't introduce any magic?) that describes what happened. 一个动作是一个简单的JavaScript对象(请注意我们如何不引入任何魔法?)来描述发生了什么。 Here are a few example actions: 以下是一些示例操作:

 { type: 'ADD_TODO', text: 'Go to swimming pool' } { type: 'TOGGLE_TODO', index: 1 } { type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' } 

Enforcing that every change is described as an action lets us have a clear understanding of what's going on in the app. 强制将每个更改描述为一个操作,让我们清楚地了解应用程序中发生的情况。 If something changed, we know why it changed. 如果发生了变化,我们就知道它为什么会改变 Actions are like breadcrumbs of what has happened. 行动就像发生了什么的面包屑。 Finally, to tie state and actions together, we write a function called a reducer. 最后,为了将状态和动作联系在一起,我们编写了一个名为reducer的函数。 Again, nothing magic about it — it's just a function that takes state and action as arguments, and returns the next state of the app. 再一次,它没有什么神奇之处 - 它只是一个将状态和动作作为参数的函数,并返回应用程序的下一个状态。 It would be hard to write such a function for a big app, so we write smaller functions managing parts of the state: 为大型应用程序编写这样的函数会很困难,所以我们编写管理状态部分的较小函数:

 function visibilityFilter(state = 'SHOW_ALL', action) { if (action.type === 'SET_VISIBILITY_FILTER') { return action.filter; } else { return state; } } function todos(state = [], action) { switch (action.type) { case 'ADD_TODO': return state.concat([{ text: action.text, completed: false }]); case 'TOGGLE_TODO': return state.map((todo, index) => action.index === index ? { text: todo.text, completed: !todo.completed } : todo ) default: return state; } } 

And we write another reducer that manages the complete state of our app by calling those two reducers for the corresponding state keys: 我们编写另一个reducer来管理应用程序的完整状态,方法是调用相应状态键的两个reducers:

 function todoApp(state = {}, action) { return { todos: todos(state.todos, action), visibilityFilter: visibilityFilter(state.visibilityFilter, action) }; } 

This is basically the whole idea of Redux. 这基本上是Redux的整个想法。 Note that we haven't used any Redux APIs. 请注意,我们没有使用任何Redux API。 It comes with a few utilities to facilitate this pattern, but the main idea is that you describe how your state is updated over time in response to action objects, and 90% of the code you write is just plain JavaScript, with no use of Redux itself, its APIs, or any magic. 它附带了一些实用程序来促进这种模式,但主要的想法是描述你的状态如何随着时间的推移而更新以响应操作对象,并且你编写的90%的代码只是简单的JavaScript,没有使用Redux本身,它的API,或任何魔术。


#6楼

Here is the simple explanation of Redux over Flux. 以下是Redux over Flux的简单解释。 Redux does not have a dispatcher.It relies on pure functions called reducers. Redux没有调度程序。它依赖于名为reducers的纯函数。 It does not need a dispatcher. 它不需要调度员。 Each actions are handled by one or more reducers to update the single store. 每个操作由一个或多个Reducer处理以更新单个存储。 Since data is immutable, reducers returns a new updated state that updates the store 由于数据是不可变的,因此reducers返回更新存储的新更新状态 在此输入图像描述

For more information Flux vs Redux 有关Flux vs Redux的更多信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值