React-starter-kit: How to: Installing Mobx instead of Redux?

Created on 1 Feb 2017  路  4Comments  路  Source: kriasoft/react-starter-kit

I've had a pretty hard time getting Mobx to work and I assume others have been as well.

So (a) I thought I'd share my changes to RSK below.

And, (b) I think it might be helpful if the RSK included MOBX since since is such an architectural improvement over the earlier models. In fact, I am not sure why React/Mobx/Typescript isn't the 'go to' toolkit since the code is much more readable and maintainable.

=== install the following ===

npm install mobx --save
npm install mobx-react --save
npm install --save-dev babel-plugin-transform-class-properties
npm install --save-dev babel-plugin-transform-decorators-legacy
npm install --save-dev babel-preset-stage-1
npm install --save-dev babel-cli babel-preset-es2015
npm install --save-dev babel-plugin-transform-object-assign
npm install --save-dev babel-plugin-array-includes


=== Modify this section of webpack.config.js ===

query: {
          // https://github.com/babel/babel-loader#options
          cacheDirectory: isDebug,

          // https://babeljs.io/docs/usage/options/
          babelrc: false,
          presets: [
            // Latest stable ECMAScript features
            // https://github.com/babel/babel/tree/master/packages/babel-preset-latest
            ['latest', { es2015: { modules: false } }],
            // Experimental ECMAScript proposals
            // https://github.com/babel/babel/tree/master/packages/babel-preset-stage-0
            'stage-1',  // << **HERE**
            // JSX, Flow
            // https://github.com/babel/babel/tree/master/packages/babel-preset-react
            'react',
            ...isDebug ? [] : [
              // Optimize React code for the production build
              // https://github.com/thejameskyle/babel-react-optimize
              'react-optimize',
            ],
          ],
          plugins: [
            // Externalise references to helpers and builtins,
            // automatically polyfilling your code without polluting globals.
            // https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-runtime
            "transform-decorators-legacy",  //<<< **HERE**
            'transform-runtime',
            ...!isDebug ? [] : [
              // Adds component stack to warning messages
              // https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
              'transform-react-jsx-source',
              // Adds __self attribute to JSX which React will use for some warnings
              // https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
              'transform-react-jsx-self',
            ],
          ],
        },

===

And check package.json matches this:

{
  "name": "web",
  "version": "0.0.0",
  "private": true,
  "engines": {
    "node": ">=6.5",
    "npm": ">=3.10"
  },
  "dependencies": {
    "babel-polyfill": "^6.22.0",
    "babel-runtime": "^6.22.0",
    "bluebird": "^3.4.7",
    "body-parser": "^1.16.0",
    "classnames": "^2.2.5",
    "cookie-parser": "^1.4.3",
    "core-js": "^2.4.1",
    "express": "^4.14.1",
    "express-graphql": "^0.6.2",
    "express-jwt": "^5.1.0",
    "fastclick": "^1.0.6",
    "fbjs": "^0.8.8",
    "graphql": "^0.9.1",
    "history": "^4.5.1",
    "isomorphic-style-loader": "^1.1.0",
    "jsonwebtoken": "^7.2.1",
    "mobx": "^2.7.0",
    "mobx-react": "^3.5.9",
    "node-fetch": "^1.6.3",
    "normalize.css": "^5.0.0",
    "passport": "^0.3.2",
    "passport-facebook": "^2.1.1",
    "pretty-error": "^2.0.2",
    "query-string": "^4.3.1",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "sequelize": "^3.30.1",
    "source-map-support": "^0.4.11",
    "sqlite3": "^3.1.8",
    "universal-router": "^2.0.0",
    "whatwg-fetch": "^2.0.2"
  },
  "devDependencies": {
    "assets-webpack-plugin": "^3.5.1",
    "autoprefixer": "^6.7.2",
    "babel-cli": "^6.22.2",
    "babel-core": "^6.22.1",
    "babel-eslint": "^7.1.1",
    "babel-loader": "^6.2.10",
    "babel-plugin-rewire": "^1.0.0",
    "babel-plugin-transform-class-properties": "^6.22.0",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-object-assign": "^6.22.0",
    "babel-plugin-transform-runtime": "^6.22.0",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-latest": "^6.22.0",
    "babel-preset-react": "^6.22.0",
    "babel-preset-react-optimize": "^1.0.1",
    "babel-preset-stage-0": "^6.22.0",
    "babel-preset-stage-1": "^6.22.0",
    "babel-register": "^6.22.0",
    "babel-template": "^6.22.0",
    "babel-types": "^6.22.0",
    "browser-sync": "^2.18.7",
    "chai": "^3.5.0",
    "chokidar": "^1.6.1",
    "css-loader": "^0.26.1",
    "editorconfig-tools": "^0.1.1",
    "enzyme": "^2.7.1",
    "eslint": "^3.14.1",
    "eslint-config-airbnb": "^14.0.0",
    "eslint-loader": "^1.6.1",
    "eslint-plugin-css-modules": "^2.1.0",
    "eslint-plugin-import": "^2.2.0",
    "eslint-plugin-jsx-a11y": "^3.0.2",
    "eslint-plugin-react": "^6.9.0",
    "extend": "^3.0.0",
    "file-loader": "^0.10.0",
    "front-matter": "^2.1.2",
    "git-repository": "^0.1.4",
    "glob": "^7.1.1",
    "json-loader": "^0.5.4",
    "lint-staged": "^3.3.0",
    "markdown-it": "^8.2.2",
    "mkdirp": "^0.5.1",
    "mocha": "^3.2.0",
    "pixrem": "^3.0.2",
    "pleeease-filters": "^3.0.0",
    "postcss": "^5.2.11",
    "postcss-calc": "^5.3.1",
    "postcss-color-function": "^2.0.1",
    "postcss-custom-media": "^5.0.1",
    "postcss-custom-properties": "^5.0.1",
    "postcss-custom-selectors": "^3.0.0",
    "postcss-flexbugs-fixes": "^2.1.0",
    "postcss-loader": "^1.2.2",
    "postcss-media-minmax": "^2.1.2",
    "postcss-nested": "^1.0.0",
    "postcss-nesting": "^2.3.1",
    "postcss-partial-import": "^3.1.0",
    "postcss-pseudoelements": "^3.0.0",
    "postcss-selector-matches": "^2.0.5",
    "postcss-selector-not": "^2.0.0",
    "postcss-url": "^5.1.2",
    "pre-commit": "^1.2.2",
    "raw-loader": "^0.5.1",
    "react-addons-test-utils": "^15.4.2",
    "react-deep-force-update": "^2.0.1",
    "react-hot-loader": "^3.0.0-beta.6",
    "redbox-react": "^1.3.3",
    "rimraf": "^2.5.4",
    "sinon": "^2.0.0-pre.5",
    "stylefmt": "^5.1.1",
    "stylelint": "^7.7.1",
    "stylelint-config-standard": "^15.0.1",
    "url-loader": "^0.5.7",
    "webpack": "^2.2.1",
    "webpack-dev-middleware": "^1.9.0",
    "webpack-hot-middleware": "^2.16.1",
    "write-file-webpack-plugin": "^3.4.2"
  },
  "babel": {
    "presets": [
      "react",
      "stage-1",
      "es2015"
    ],
    "plugins": [
      "syntax-trailing-function-commas",
      "array-includes",
      "transform-decorators-legacy",
      "transform-class-properties",
      "transform-async-to-generator",
      "transform-es2015-destructuring",
      "transform-es2015-parameters",
      "transform-es2015-duplicate-keys",
      "transform-es2015-modules-commonjs",
      "transform-exponentiation-operator",
      "transform-runtime"
    ],
    "env": {
      "test": {
        "plugins": [
          "rewire"
        ]
      }
    }
  },
  "eslintConfig": {
    "parser": "babel-eslint",
    "extends": [
      "airbnb",
      "plugin:css-modules/recommended"
    ],
    "plugins": [
      "css-modules"
    ],
    "globals": {
      "__DEV__": true
    },
    "env": {
      "browser": true
    },
    "rules": {
      "arrow-parens": "off",
      "generator-star-spacing": "off",
      "import/extensions": "off",
      "import/no-extraneous-dependencies": "off",
      "react/forbid-prop-types": "off",
      "react/jsx-filename-extension": "off",
      "react/no-array-index-key": "off",
      "react/no-danger": "off",
      "react/no-unused-prop-types": "off",
      "react/prefer-stateless-function": "off",
      "react/require-default-props": "off"
    }
  },
  "stylelint": {
    "extends": "stylelint-config-standard",
    "rules": {
      "string-quotes": "single",
      "property-no-unknown": [
        true,
        {
          "ignoreProperties": [
            "composes"
          ]
        }
      ],
      "selector-pseudo-class-no-unknown": [
        true,
        {
          "ignorePseudoClasses": [
            "global"
          ]
        }
      ]
    }
  },
  "pre-commit": "lint:staged",
  "lint-staged": {
    "*.{md,sh,txt,xml,html,json}": [
      "editorconfig-tools fix",
      "git add"
    ],
    "*.{js,jsx}": [
      "eslint --fix",
      "git add"
    ],
    "*.{css,less,scss,sss}": [
      "stylefmt",
      "stylelint",
      "git add"
    ]
  },
  "scripts": {
    "lint:js": "eslint src tools",
    "lint:css": "stylelint \"src/**/*.{css,less,scss,sss}\"",
    "lint:staged": "lint-staged",
    "lint": "yarn run lint:js && yarn run lint:css",
    "test": "mocha \"src/**/*.test.js\" --require babel-register --require test/setup.js",
    "test:watch": "yarn run test -- --reporter min --watch",
    "clean": "babel-node tools/run clean",
    "copy": "babel-node tools/run copy",
    "bundle": "babel-node tools/run bundle",
    "build": "babel-node tools/run build",
    "deploy": "babel-node tools/run deployToAzureWebApps",
    "render": "babel-node tools/run render",
    "serve": "babel-node tools/run runServer",
    "start": "babel-node tools/run start"
  }
}

example

Most helpful comment

Here's the same with yarn, off of master branch
CLI install:

yarn add mobx mobx-react
yarn add babel-plugin-transform-class-properties babel-plugin-transform-decorators-legacy --dev

Add to package.json:

plugins: [
  'transform-decorators-legacy',
  // all existing plugins
],

All 4 comments

Here's the same with yarn, off of master branch
CLI install:

yarn add mobx mobx-react
yarn add babel-plugin-transform-class-properties babel-plugin-transform-decorators-legacy --dev

Add to package.json:

plugins: [
  'transform-decorators-legacy',
  // all existing plugins
],

Thanks. And I assume I can just uninstall Redux?

Can anybody give us opinions on MobX? What is great on it and what is pain?

@curtd59 My team is also looking to use TypeScript and MobX, and it would be good to see MobX as a feature branch (just as Redux is a feature branch).

We're attracted to the idea of reactive pattern to managing state; it seems less verbose than having to write up actions, action creators, and reducers with switch cases. With MobX, you write and invoke direct state mutations, so from a code maintainability perspective, it seems more concise. We'll find out eventually if there is any impact on debuggability. At least with Redux, you can do time rewinding via the Redux Dev Tools. There is a similar capability with mobx-state-tree, but as this will be the first time anyone from my team is using MobX, we're going to dive in and see what happens!

Was this page helpful?
0 / 5 - 0 ratings