MobX或Redux:哪个更适合React状态管理?



在JavaScript中,状态管理已成为当今讨论的热点。 在实施状态管理时,开发人员经常发现在Redux中处理样板代码具有挑战性。 因此,事实证明,MobX是Redux的不错选择,Redux以更少的代码提供相同功能。 但是,两个状态管理工具都可以与React一起很好地工作。

首先让我们看一下两者之间的共同点:

1)两者都支持时间旅行调试
2)两者都包含开源库
3)两者都提供客户端状态管理
4)两者都为React本机框架提供了巨大的支持

在此博客中,我们列出了两种状态管理解决方案的所有优点和缺点。 它将帮助网络开发人员为他们的下一个项目选择最佳的解决方案。 在讨论这一点之前,我们根据以下给出的一些参数比较了Redux和Mobx:

->维护和可扩展

由于存在纯函数和函数式编程范例,Redux更具可伸缩性和可维护性。 因此,可以使用Redux轻松控制事物。

->调试过程

与MobX相比,在Redux中进行调试是一种很好的体验,因为它提供了很棒的开发人员工具,并且抽象程度较低。 借助通量范例,Redux变得更加可预测。 另一方面,由于更多的抽象和普通的开发人员工具,MobX中的调试要困难得多。

->学习曲线

学习MobX很容易,因为它具有稳定的学习曲线。 最大抽象的存在使学习变得容易,并且熟悉OOP概念的JavaScript开发人员在MobX上拥有据点。 另一方面,Redux使用功能性编程范例,这使得很难一目了然。

->社区

与MobX相比,Redux具有庞大的社区基础。 因此,Redux可以随时随地为开发人员提供强大的社区支持。

->不纯与纯

MobX不纯,因为状态可以被覆盖。 在这里,您可以轻松地使用新值更新状态。 但是,Redux是纯函数,因为它使用纯函数。 在这里,状态是只读的,不能直接覆盖。 之前的状态被替换为新的状态。

->可观察与纯数据

MobX使用可观察的存储,而Redux使用普通的Javascript数据存储值。 在Redux中,所有更新都是手动跟踪的。

->商店

商店是放置数据的地方。 MobX具有多个存储,这些存储在逻辑上是分开的。 另一方面,Redux有一个存储所有状态的大型存储。 通常在Redux中将数据标准化,而在MobX中将数据保持非标准化状态。

Redux vs MobX:代码比较

道具注射

React-redux的connect()函数用于将状态和操作传递给Redux中的prop。 如下图所示:

//访问道具

<ContactForm contact={this.props.contact} loading={this.props.loading} onSubmit={this.submit} /> 


//将状态注入道具的函数

 function mapStateToProps(state) { return { contact: state.contactStore.contact, errors: state.contactStore.errors } } 


//将状态和动作都注入道具

 export default connect(mapStateToProps, { newContact, saveContact, fetchContact, updateContact })(ContactFormPage); 


在MobX中, 注入用于注入商店的集合。 这将使商店在道具中可用。 在这里,状态和动作是通过store对象中的属性访问的,因此无需单独传递它们。

 @inject("stores") @observer // injecting store into props class ContactFormPage extends Component { … // accessing store via props const { contactStore:store } = this.props.stores; return ( <ContactForm store={store} form={this.form} contact={store.entity} /> ) … } 


因此,我们使用redux-connect-decorators简化了Redux代码,并且MobX版本始终易于阅读。 因此,没有这样明确的赢家。

自举

在Redux中,首先定义存储区,然后通过Provider传递App。 要处理异步功能,您还需要定义redux-thunk和redux-promise-middleware。 此后,redux-devtools-extension允许调试以时间旅行模式存储。

 import { applyMiddleware, createStore } from "redux"; import thunk from "redux-thunk"; import promise from "redux-promise-middleware"; import { composeWithDevTools } from 'redux-devtools-extension'; import rootReducer from "./reducers"; const middleware = composeWithDevTools(applyMiddleware(promise(), thunk)); export default createStore(rootReducer, middleware); 


// src / index.js

 ReactDOM.render( <BrowserRouter> <Provider store={store}> <App /> </Provider> </BrowserRouter>, document.getElementById('root') ); 


在MobX中,设置了多个商店。 它不需要外部库来处理异步操作,而只需几行代码。 您需要mobx-remotedev来连接redux-devtools-extension调试工具。



 import remotedev from 'mobx-remotedev'; import Store from './store'; const contactConfig = { name:'Contact Store', global: true, onlyActions:true, filters: { whitelist: /fetch|update|create|Event|entity|entities|handleErrors/ } }; const contactStore = new Store('api/contacts'); const allStores = { contactStore: remotedev(contactStore, contactConfig) }; export default allStores; 


// src / index.js

 ReactDOM.render( <BrowserRouter> <Provider stores={allStores}> <App /> </Provider> </BrowserRouter>, document.getElementById('root') ); 


但是,两者中使用的代码量相同。 但是,MobX包含的导入语句更少。

定义动作和减速器

通过以下代码在Redux中定义了动作和缩减器:

//动作

 export function fetchContacts(){ return dispatch => { dispatch({ type: 'FETCH_CONTACTS', payload: client.get(url) }) } } 


//减速器

 switch (action.type) { case 'FETCH_CONTACTS_FULFILLED': { return { ...state, contacts: action.payload.data.data || action.payload.data, loading: false, errors: {} } } case 'FETCH_CONTACTS_PENDING': { return { ...state, loading: true, errors: {} } } case 'FETCH_CONTACTS_REJECTED': { return { ...state, loading: false, errors: { global: action.payload.message } } } } 


动作和减速器的逻辑是在MobX中的一类中完成的。 由于使用OOP,Store类被重构以使用类构造函数创建多个商店。 相应的代码如下所示:

 @action fetchAll = async() => { this.loading = true; this.errors = {}; try { const response = await this.service.find({}) runInAction('entities fetched', () => { this.entities = response.data; this.loading = false; }); } catch(err) { this.handleErrors(err); } } 


因此,我们已经看到,两种状态管理解决方案中定义的逻辑都可以完成相同的工作。 唯一的不同是,我们在Redux中使用了33行代码,在MobX中使用了14行代码来获得结果。 因此,您可以使用MobX更快地构建应用程序。

为什么要将MobX用于React应用程序?

MobX是经过测试的库,可通过透明地应用功能反应式编程(TFRP)使状态管理变得简单且可扩展。 React和MobX是强大的组合。

  • 减少编写代码
  • 易学
  • 嵌套数据很容易
  • 支持面向对象的编程


为什么不使用MobX?

  • 难以调试
  • 更好的替代品
  • 给予过多的自由


为什么要将Redux用于React应用程序?

Redux是一个独立的库,可以与UI框架一起使用,包括Angular,Vue,Ember,React和vanilla JS。

  • 通过中间件的可扩展性
  • 人气与社区
  • 工具支持
  • 可预测性和简单性
  • 单向数据流和不变性
  • 数据和表示分离


为什么不使用Redux?

  • 样板(还原器,选择器,视图,操作类型,操作创建者,...)
  • 动作已脱离其效果(在reduce中定义)
  • 没有现成的解决副作用的解决方案(可通过redux-thunk或redux-saga等中间件获得)


最后说明:

现在,您可以看到MobX代码库更加敏捷。 使用OOP风格和良好的开发实践,您可以快速创建React应用程序。 主要缺点是编写不良代码非常容易,并且无法维护。

另一方面,Redux很受欢迎,适合于构建大型和复杂的项目。 这是一个带有防护措施的严格框架,可确保每个开发人员编写易于测试和维护的代码。 但是,它不适合小型项目。

我希望我提供了足够的信息来阐明是迁移到MobX还是继续使用Redux。 最终,决定取决于您正在从事的项目类型和可用资源。

Source: https://habr.com/ru/post/zh-CN480692/


All Articles