Redux or MobX -

Β 

What Should I Pick For My React App?

Outline

  • What Problem Are We Trying To Solve
  • What Is Redux
  • What Is MobX
  • Showcase
  • Comparison
  • Conclusion / Q&A

What Problem Are We Trying To Solve

const UserCard = ({ user }) => (
  <div>
    <p> Name: {user.name} </p>
    <p>  Age: {user.age} </p>
  </div>
)

class UserPage extends Component {
  userData = {}

  componentDidMount() {
    // Fetch information of current user
    fetch('https://restful-api-endpoint.com/v1/user/30678')
      .then(res => res.json())
      .then(json => this.setState({ userData: json }))
  }

  render() {
    return (
      <>
        <UserCard user={this.state.userData} />
      </>
    )
  }
}

A simple but usual case:
Developing a SPA and handle routes by react router.

class AboutMePage extends Component {
  render() {
    const { userData } = this.state

    return (
      <>
        Welcome {userData.name}! Check your information below.
        <UserCard user={userData} />
      </>
    )
  }
}

const Sidebar = ({ user }) => (
  <>
    <Header user={user} />
    <Menu>
      <MenuItem>Homepage</MenuItem>
      <MenuItem>About Me</MenuItem>
      <MenuItem>Posts</MenuItem>
    </Menu>
  </>
)

const Header = ({ user }) => (
  <UserCard user={userData} />
)

Imagine that we have to display UserCard UI with the shared data otherwhere.

So, what can we do before
v16.3 released?

class AppRoot extends Component {
  userData = {}

  componentDidMount() {
    // Fetch information of current user
    fetch('https://restful-api-endpoint.com/v1/user/30678')
      .then(res => res.json())
      .then(json => this.setState({ userData: json }))
  }
 
  render() {
    const { userData } = this.state

    return (
      <BrowserRouter>
        <Sidebar user={userData} />
        <Switch>
          <Route
            path="/about"
            render={routeProps => <AboutMePage {...routeProps} user={userData} />}
          />
          <Route
            path="/user"
            render={routeProps => <UserPage {...routeProps} user={userData} />}
          />
        </Switch>
      </Router>
    )
  }
}

There is a simple and intuitive solution.

Prop Drilling

https://www.carlrippon.com/playing-with-the-context-api-in-react-16-3/

There're still some problems
Context API can not solve

  • Cross-Cutting Concerns
  • Asynchronous Calls and Side Effects
  • Predictable Dataflow

What Is Redux

Redux Highlight

  • A state management solution
  • Single Source of Truth (SSOT)
  • Inspired by flux and influenced by FP
  • Popular and Well-developed ecosystem

When to Use?

  1. When you want to avoid prop drilling.
  2. When some states should be shared between more than one components.
  3. When you want to manipulate global or top-level component. (e.g. Notification, Toast, Modal, Tooltips.)
  4. When you want to write applications that behave consistently.
  5. When the UI and business logic youΒ faced is too complex to handle currently.

https://itnext.io/integrating-semantic-ui-modal-with-redux-4df36abb755c

What Is MobX

MobX Highlight

  • A least obtrusive libraries you can use for state management.
  • Make state managements simple by Functional Reactive Programming (FRP) paradigm.
  • No need to normalize your data anymore.
  • Be Reactive!
  • Simple.

Overview

Core Concepts

  • Observable State
  • Computed values
  • Reactions
  • Actions

Observable State

import { observable } from 'mobx'

const state = {
  userData: {},
}

export default observable(state)
import { observer } from 'mobx-react'
import UserCard from '../components/UserCard'
import state from './state'

const Comp = () => (
  <>
    <UserCard user={state.data} />
  </>
)

export default observer(Comp)

Computed Values

class TodoList {
  @observable todos = []
  @computed get unfinishedTodoCount() {
    return this.todos.filter(todo => !todo.finished).length
  }
}
import { decorate, observable } from "mobx"

class TodoList {
  todos = []
  get unfinishedTodoCount() {
    return this.todos.filter(todo => !todo.finished).length
  }
}

decorate(TodoList, {
  todos: observable,
  unfinishedTodoCount: computed
})

Reactions

@observer
class TodoListPage extends Component {
  const { store } = this.props

  render() {
    return (
      <div>
        <ul>
          {
            store.todos.map(todo => <TodoItem todo={todo} key={todo.id} />)
          }
        </ul>
        Tasks left: {store.todos.unfinishedTodoCount}
      </div>
    )
  }
}

const TodoItem = observer(({ todo }) =>
  <li>
    <input
      type="checkbox"
      checked={todo.finished}
      onClick={() => todo.finished = !todo.finished}
    />
    {todo.title}
  </li>
)

const store = new TodoList()
ReactDOM.render(<TodoListPage store={store} />, document.getElementById('app'))

Actions

Unlike many flux frameworks, MobX is unopinionated about how user events should be handled.

  • This can be done in a Flux like manner.

  • Or by processing events using RxJS.

  • Or by simply handling events in the most straightforward way possible, as demonstrated in the above onClick handler.

There is no technical need for firing events, calling a dispatcher or what more. A React component in the end is nothing more than a fancy representation of your state. A derivation that will be managed by MobX.

import { action, observable } from 'mobx'

const state = {
  userData: {},
  getUserData: action(function() {
    fetch('https://restful-api-endpoint.com/v1/user/30678')
      .then(res => {
        this.userData = res
      })
  })
}

export default observable(state)

Showcase

Comparison

Redux

Mobx

  • Single store (SSOT)

  • FP paradigm

  • Pure

  • Explicit update logic and dataflow

  • More boilerplate

  • Normalized state

  • Multiple stores

  • RFP paradigms

  • Impure

  • Implicit update logic and dataflow

  • Less boilerplate

  • Denormalized state

Redux MobX
Easy to learn πŸ‘ πŸ‘πŸ‘πŸ‘
Scalability πŸ‘πŸ‘πŸ‘ πŸ‘πŸ‘
Testability πŸ‘πŸ‘πŸ‘ πŸ‘
Predictability πŸ‘πŸ‘πŸ‘ πŸ‘πŸ‘
Line of code πŸ‘ πŸ‘πŸ‘πŸ‘
Managing Asynchronous Calls βœ… βœ…
Handling Side Effects βœ… βœ…
​Separation of Concerns (SoC) βœ… βœ…

Conclusion

Q&A

Redux or MobX - What Should I Pick For My React App?

By hinx

Redux or MobX - What Should I Pick For My React App?

  • 821