[React源码剖析系列 - 生命周期的管理艺术] (https://www.w3ctech.com/topic/1596)
MobX 相关
http://www.tuicool.com/articles/UZVZJnY
Redux 对 action / event 作出反应,而 MobX 对 state 变化作出反应。在更新逻辑方面,MobX 是在 store 内进行相应封装,假设一个 UI 操作需要更新多个 store 内的值时,那么我们需要多次触发对应 action,或者在多个 store 上再添加一个 store 去进行控制,这都不如 Redux 来得优雅,Redux 只需要触发一个 action,多个 reducer 可响应相同的 action type,即可完成更新。
首先,让我们来回顾一下mobx的核心概念:
可观测状态
状态是指任何可以改变并且会引发计算属性变化的值。mobx可以把大多数类型的值(基础类型、数组、各种对象),都转化成可观测的。而且针对,数组或对象等的结构化的数据类型,这种转化是递归的,数组或对象的所有子节点都会被转化。
计算属性
计算属性是一个函数。这个函数不接收参数,只单纯的依赖的其他可观测状态。依赖的可观测状态发生变化,它的运行结果才会发生变化。
虽然和定义有一定出入,但是从输入输出保持一致这点来看,计算属性应该算是一种纯函数。
很多场景都能用到计算属性,比如字符串的连接,或者生成复杂结构的对象。因为计算属性自身也是可观测的,所以甚至可以使用它从可观测状态导出完整的用户界面。计算属性还可以在惰性和活跃两种状态之间切换。
反应
反应和计算属性有点类似,不同点在于,计算属性的函数是产生一个新的值,而反应是产生一个副作用。所谓副作用,就是指一些跟计算无关的动作,比如打印日志,网络请求,更新界面之类的。总之使用反应可以把数据变化和其他流程关联起来。
动作
动作是修改状态的主要方法。动作本身并不对状态更改做响应,而是修改可观测状态。(如用户触发的事件、web-socket传入消息、或直接对可观测状态的修改)
这四个核心概念对应mobx中最常用的4个api,observable、computed、reaction(autorun)、action。
React 单元测试
React+Redux单元测试一小时入门
要测试 ajax 请求,可以用 sinon 的 fake XMLHttpRequest, 不用为了测试改动 action 任何代码:
Unit testing react component that makes ajax calls using JEST
How to implement testing + code coverage on React with Karma, Babel, and Webpack
最近陸續用 Redux 做了一些 projects,想要把一些心得整理出來。
目前預計整理三篇:
Hello Redux: 關於 Redux 的一些基本介紹,包括我認知的 redux 的一些概念,和我覺得他設計得很棒的地方。
Server Rendering: 介紹如何使用 Redux 和 react-router 做 server rendering (ya! 寫好惹!)
Unit Test: 在測 Redux 的 code 的時候我遇到的問題和解決的方法,還有怎麼在測試的時候和 webpack loaders 和平共處。
這篇文章是這個系列的第三部份,Unit Test。
再看看Coverage,卧槽。。居然不是百分之百了。。。
原因很简单,webpack会加入一些代码,影响了代码的Coverage。如果我们引入了一些其它的库,比如jquery之类的,将源代码和库代码打包在一起后,覆盖率会更难看。。这样的Coverage就没有了参考的价值。
typescriptのunit test(webpack2, karma, jasmine, chai)
karma.conf.js
// Karma configuration
// Generated on Sat Jan 21 2017 10:54:02 GMT+0900 (JST)
const webpackConfig = require('./test.webpack.conf');
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '.',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine', 'karma-typescript'],
// list of files / patterns to load in the browser
files: [
'src/**/*.ts',
'test/unit/index.spec.ts',
],
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/unit/index.spec.ts': ['webpack', 'sourcemap'],
'src/**/*.ts': ['webpack', 'karma-typescript'],
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['mocha', 'karma-typescript'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
// phantomjs configuration
phantomjsLauncher: {
// Have phantomjs exit if a ResourceError is encountered (useful if karma exits without killing phantom)
exitOnResourceError: true
},
// webpack configuration
webpack: webpackConfig,
// webpack-dev-middleware configuration
webpackMiddleware: {
stats: 'errors-only'
},
coverageReporter: {
reporters: [
{ type: 'text-summary' },
]
},
})
}