Redux vs MobX毫不困惑

图片

近年来,我经常使用Redux,但是最近我一直在使用MobX作为状态管理的替代方法。 Redux的替代品似乎自然变成了一片混乱。人们不确定要选择哪种解决方案。问题不一定是Redux vs MobX。只要有其他选择,人们就会好奇如何最好地解决他们的问题。我写这些行是为了消除围绕Redux和MobX状态管理解决方案的困惑。

这篇文章将是关于什么的?首先,我想简单地回到状态管理库解决的问题。最后,如果仅在React或其他表示层库或SPA环境中使用this.setState()和this.state,一切都会很好。其次,我将继续为您提供两种解决方案的概述,以显示一致性和差异性。最后但并非最不重要的一点是,如果您已经拥有可与MobX或Redux一起使用的应用程序,那么我想告诉您有关从一个状态库重构到另一个状态库的信息。

内容:


  1. 我们要解决什么问题?
  2. REDUX和MOBX有什么区别?
  3. 反应状态学习曲线
  4. 关于这个话题的最新想法
  5. 更多资源


我们要解决什么问题?


每个人都希望在应用程序中具有状态管理。但是,这为我们解决了什么问题?大多数人从一个小型应用程序开始,并且已经实现了状态管理库。每个人都在谈论它,对不对?Redux!MobX!但是大多数应用程序从一开始就不需要雄心勃勃的状态管理。这甚至更加危险,因为大多数人将永远不会遇到诸如Redux或MobX之类的库的问题

现状目前正在构建带有组件的前端应用程序。组件具有内部状态。在不断增长的应用程序中,状态管理可能会因本地状态而变得混乱,因为:

  • 一个组件必须与另一个组件共享状态
  • 一个组件必须修改另一个组件的状态

在某些时候,谈论应用程序的状态变得越来越困难。这将成为组件层次结构中状态对象和状态突变的肮脏网络。在大多数情况下,状态对象和状态突变不一定与一个组件相关联。它们通过组件树链接,并且您必须升高和降低状态。

因此,解决方案是引入状态管理库,例如MobX或Redux。它为您提供了保存状态,更改状态和接收状态更新的工具。您可以在一个位置进行搜索,在一个位置进行更改,并在一个位置接收状态更新。他遵循单一真理来源原则。由于状态和条件的变化与组件分离,因此这使您更容易推断状态和条件的变化。

状态管理库(例如Redux和MobX)通常具有实用程序的附加组件,例如,对于Angular,它们具有angular-redux和mobx-angular,以使您的组件能够访问状态。通常,这些组件称为容器化组件,或更准确地说,称为相关组件您可以从组件层次结构中的任何位置访问状态并通过将组件更新为相关的状态来更改状态。


REDUX和MOBX有什么区别?


在深入探讨差异之前,我想向您介绍MobX和Redux之间的相似之处。

这两个库都用于控制JavaScript应用程序中的状态。它们不一定与Angular之类的库关联。它们还用于其他库中,例如ReactJ和VueJ。

如果选择一种状态管理解决方案,则不会遇到供应商停工的情况。您可以随时切换到另一个状态管理解决方案。您可以从MobX升级到Redux或从Redux升级到MobX。稍后,我将向您展示这种情况。

Dan AbramovAndrew Clark设计的Redux Flux架构的衍生产品。与Flux不同,它使用多个存储库中的一个来维护状态。此外,它使用纯函数代替调度程序来更改状态。如果您对流程不熟悉并且不熟悉状态管理,则不必担心最后一段。

Redux受功能编程(FP)原理的影响。 FP可以用JavaScript完成,但是许多人来自Java等面向对象的背景,一开始就难以接受函数式编程的原理。稍后将解释为什么MobX作为初学者可能更容易学习。

由于Redux包含函数式编程,因此它使用纯函数
纯函数是接收输入,返回输出并且除相同函数外没有其他依赖项的函数。这样的功能总是产生具有相同输入的相同输出,并且没有副作用。更多细节

(state, action) => newState

您的Redux状态保持不变而不是变异,您总是返回一个新状态。您不执行状态突变,也不依赖于对象引用。


//     Redux,     
function addAuthor(state, action) {
  return state.authors.push(action.author);
}
//       
function addAuthor(state, action) {
  return [ ...state.authors, action.author ];
}

最后但并非最不重要的一点,在惯用的Redux中,您的状态已规范化,就像在数据库中一样。实体仅通过id相互引用。这是最佳做法。尽管并非所有人都可以,但是您可以使用normalizr之类的库来实现这种标准化状态。规范化状态使您可以保持平坦状态和实体作为单一事实来源

{
  post: {
    id: 'a',
    authorId: 'b',
    ...
  },
  author: {
    id: 'b',
    postIds: ['a', ...],
    ...
  }
}



相比之下,Michel Weststratt的MobX不仅受到面向对象编程的影响,还受到反应式编程的影响。它将状态包裹在可观察的对象中。因此,您在自己的状态下具有“ 可观察 ”的所有功能数据可以具有简单的setter和getter,但是可观察的数据使您可以在数据更改后接收更新。

在Mobx中,您的状态是volatile这样,您可以直接更改状态:

function addAuthor(author) {
  this.authors.push(author);
}

此外,组织之间保持相对(深层)嵌套的数据结构。您没有使您的状况正常化。条件保持非规范化并嵌入。

{
  post: {
    id: 'a',
    ...
    author: {
      id: 'b',
      ...
    }
  }
}

一个存储库与几个存储库


在Redux中,您将所有状态存储在一个全局存储库一个全局状态中。单个状态对象是您唯一的真理来源。另一方面,许多变速箱允许它改变不变的状态。

相比之下,MobX使用几个存储库。像Redux减速器一样,您可以按技术水平,领域等应用分隔和征服。您可以将域对象存储在单独的存储库中,但也可以控制存储库中的查看状态。最后,您放置最适合您的应用程序的状态。

从技术上讲,您也可以在Redux中拥有多个存储库。没有人会强迫您只使用一个。但这不是Redux宣传的用例。使用多个存储库与最佳做法背道而驰。在Redux中,您希望有一个存储库,通过其简化器响应全局事件。

实现是什么样的?


在Redux上,将应用程序的配置添加到全局状态需要以下代码行。

const initialState = {
  users: [
    {
      name: 'Alex'
    },
    {
      name: 'Nik'
    }
  ]
};
// reducer
function users(state = initialState, action) {
  switch (action.type) {
  case 'USER_ADD':
    return { ...state, users: [ ...state.users, action.user ] };
  default:
    return state;
  }
}
// action
{ type: 'USER_ADD', user: user };

在MobX中,存储将仅管理子状态(因为Redux中的reducer控制子状态),但是您可以直接更改状态。@observable批注允许您观察状态变化。

class userStore{
@observable users = [
    {
      name: 'Nikita'
    }
  ];
}

现在您可以调用userStore.users.push(用户);在商店的副本上。但是,建议通过操作使状态突变更明确。

class userStore{
@observable users = [
    {
      name: 'Nikita'
    }
  ];
}
@action addUser = (user) => {
    this.users.push(user);
  }

您可以通过使用configure({empceActions:true});配置MobX来严格应用它。现在,您可以通过调用userStore.addUser(用户)来更改状态。在商店的副本上。

您已经了解了如何在Redux和MobX上更新状态。在Redux中,您的状态为只读您只能通过显式操作更改状态相反,在MobX中,状态包括读取和写入。您可以不使用操作直接更改状态,但是可以使用forcenActions配置选择显式操作。


反应状态学习曲线


Redux和MobX都主要用于React应用程序。但是这些都是独立的状态管理库,无需React即可在任何地方使用。它们的交互库使将它们与Angular组件轻松组合成为可能。这些反应-终极版阵营+终极版mobx反应的用于阵营+ MobX。稍后我将解释如何在Angular组件树中同时使用两者。

在最近的讨论中,确实发生了人们争论Redux中的学习曲线的问题。这通常是在React上下文中发生的:人们开始学习React,并已经想在Redux中使用状态管理。大多数人认为React和Redux本身具有良好的学习曲线,但是两者都可能令人不知所措。因此,MobX将是替代方案,因为它更适合初学者。

但是,对于新的React用户,我建议使用另一种方法来了解React生态系统中的状态管理。开始学习在组件中使用自己的本地状态管理功能进行React。在React应用程序中,您首先要了解React生命周期方法,并了解如何使用setState()和this.state管理本地状态。我强烈推荐这种学习方式。否则,您将很快被React生态系统淹没。最后,您将逐渐认识到管理组件的(内部)状态变得很复杂。

Redux或MobX适合初学者?


通过熟悉Angular组件和内部状态管理,您可以选择状态管理库来解决您的问题。在使用完这两个库之后,我会说MobX对于初学者来说可能非常方便。我们已经看到MobX需要更少的代码,尽管它确实使用了一些我们不需要知道的魔术笔记。
使用MobX,您无需熟悉函数式编程。不变性之类的术语可能仍然是外国的。
— , JavaScript. , , - , , MobX.


Redux


随着您的应用程序变得越来越大,并且有多个开发人员在处理它,您应该考虑使用Redux。本质上,他承诺使用明确的行为来改变状态。动作具有齿轮箱可以用来改变状态的类型和有效载荷。开发团队以这种方式谈论状态变化非常容易。

Redux为您提供了一个完整的体系结构,用于管理有明显限制的状态。Redux成功案例

Redux的另一个优点是在服务器端的使用。由于我们正在处理简单的JavaScript,因此您可以通过网络发送状态。状态对象的序列化和反序列化是开箱即用的。但是,MobX也可以做到这一点。

MobX不太自信,但是使用configure({empceActions:true})可以像Redux一样应用更精确的限制。这就是为什么我不会说您不能使用MobX来扩展应用程序,但是Redux有明确的方法来做某事。 MobX文档甚至说:“ [MobX]不会告诉您如何构建代码,在何处存储状态或如何处理事件。”开发团队首先必须创建一个状态管理架构。

毕竟,状态管理的学习曲线并不那么陡峭。当我们重复建议时,React的新手将首先学习如何正确使用setState()和this.state。一段时间后,您将了解仅使用setState()的问题在React应用中保持状态。在寻找解决方案时,您会遇到状态管理库,例如MobX或Redux。但是选择哪一个呢?由于MobX不太自信,具有较小的模板,并且可以与setState()类似地使用,因此我建议在小型项目中给MobX一个机会。一旦应用程序规模增加并增加参与者数量,您就应该考虑在MobX中应用其他限制或给Redux一个机会。我喜欢使用两个库。即使最后不使用其中之一,也有必要找到一种替代方法来管理状态。


最后的想法


每当我在Redux vs MobX讨论中阅读评论时,总会有一个评论:“ Redux标准太多,您应该改用MobX。我能够删除XXX行代码。“该评论可能是正确的,但没有人认为妥协。 Redux附带了许多模板,例如MobX,因为它是为特定的设计约束而添加的。这使您可以推断应用程序的状态,即使它的规模更大。与国家待遇有关的整个仪式,不仅是公正的。

Redux库很小。大多数时候,您只处理简单的JavaScript对象和数组。。这比MobX更接近原始JavaScript。在MobX中,对象和数组被包裹在可观察的对象中,这些对象隐藏了大多数标准模板。它建立在其中会发生魔术的隐藏抽象之上,但是更难理解基本机制。 Redux使您可以使用简单的JavaScript轻松谈论此问题。这使得测试和调试应用程序变得容易。

此外,您需要重新考虑我们在SPA中来自何处。一堆单页框架和应用程序库具有相同的状态管理问题,这些问题最终通过使用全面的流模型得以解决。 Redux是此方法的后继者。

在MobX中,它再次朝相反的方向移动。我们再次开始直接改变状态,而无需利用功能编程。对于某些人来说,这再次接近双向数据绑定。一段时间后,人们可能会再次遇到相同的问题,然后再出现诸如Redux之类的状态管理库。状态管理分散在各个组件之间,并且混乱不堪。

在Redux上,您已经建立了设置仪式,而MobX则没有那么自信。但是最好接受MobX的最佳体验。人们需要知道如何组织状态管理,以改进他们对此的论点。否则,人们倾向于直接在组件中更改状态。

这两个库都很棒。尽管Redux已经很成熟,但是MobX正在成为状态管理的可行替代方案。


更多资源


Michel Weststratt - MobX的创建者的
比较

All Articles