redux mobx 对比 区别

657 阅读2分钟

本文使用的库版本如下:

mobx v6
mobx-react v7
redux v4
react-redux v7

使用redux开发,同时需要维护action,reducer,即使是借助redux-thunk或者redux-saga这样的中间件,action这一层的代码量感觉还是太多了,光是actionType的命名都需要斟酌思考,mobx将action和reducer结合到了一起,省去了type的命名,以及es6+的装饰器的引入,整个代码量和复杂度降低了不少,自从用了mobx工作效率提升了不少。另外mobx的store是可以组件化的,不需要像redux去维护一个整体的store。但是正因为redux有这样多的样板代码,所以使得代码的规范性增强,mobx相对来说如果没有一个合理的规范的话,使用的方式会比较多,维护性将会变差,强烈建议上mobx需要一套规范/实践

原理: redux:组件dispatch一个action,reducer接收到改变相应的数据,通过props的方式注入到组件中,组件更新。 mobx:他和redux类似数据都是单向流动,通过action改变数据,proxy监听数据改变,通知组件进行更新,

下面通过具体的demo来看下两种数据管理库的使用方式:

import React from "react"
import ReactDOM from "react-dom"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react"

// Model the application state.
class Timer {
    secondsPassed = 0

    constructor() {
        makeAutoObservable(this)
    }

    increase() {
        this.secondsPassed += 1
    }

    reset() {
        this.secondsPassed = 0
    }
}

const myTimer = new Timer()

// Build a "user interface" that uses the observable state.
const TimerView = observer(({ timer }) => (
    <button onClick={() => timer.reset()}>Seconds passed: {timer.secondsPassed}</button>
))

ReactDOM.render(<TimerView timer={myTimer} />, document.body)

// Update the 'Seconds passed: X' text every second.
setInterval(() => {
    myTimer.increase()
}, 1000)
// src/flux/Company/action.jsexport function fetchContacts(){
  return dispatch => {
    dispatch({
      type: 'FREQUEST_COMPANY_INFO',
      payload: {}
    })
  }
}
…

// src/flux/Company/reducer.js
const initialState = {};
function reducer (state = initialState, action) {
  switch (action.type) {
    case 'FREQUEST_COMPANY_INFO': {
      return {
        ...state,
        contacts: action.payload.data.data || action.payload.data,
        loading: false
      }
    }
    default:
      return state;
  }
}
// src/containers/Company.jsclass CompanyContainer extends Component {
  componentDidMount () {
    this.props.loadData({});
  }
  render () {
    return <Company
      infos={this.props.infos}
      loading={this.props.loading}
    />
  }
}
…

// function for injecting state into props
const mapStateToProps = (state) => {
  return {
    infos: state.companyStore.infos,
    loading: state.companyStore.loading
  }
}

const mapDispatchToProps = dispatch => {
  return bindActionCreators({
      loadData: loadData
  }, dispatch);
}

// injecting both state and actions into props
export default connect(mapStateToProps, { loadData })(CompanyContainer);