@(blog)
Redux basic tutorial
本文的读者为相识flux观点,熟习react,相识es6语法的同砚
redux
是近来很火的一个 flux
框架,短短的一个月如今已经有2900+的 star 了,watch以后天天收到几百封 pr 的邮件,空话就不多说了。
为何要用 redux
,请看衔接 The Evolution of Flux Frameworks。
主要特性
- Everything (Stores, Action Creators, configuration) is hot reloadable. —— 配合起 hotloader 应当迥殊爽,虽然如今用的是
browserify
,优点以为并不显著。 -
store
中的数据不受限定,可所以number
object
array
等等,空话,由于它的store
只是简朴的函数。 - 供应
devtools
,监控action
的触发以及state
的变化。 - 源码清楚简朴,轻量级,基础不须要文档,直接看源码就好了….瑕玷就是假如看不懂源码,光看文档会以为不够清楚。
-
api
很精简,不必记茫茫多的api
- every thing is simple function
-
connecter
与provider
这两个东西用起来总以为很烦琐,不那么文雅。
下面经由历程写的一个简朴counter的例子 引见 redux
的中心要领以及一些须要注重的处所。
- 同步与异步两种actionCreator
- middleware的运用
- dispatch actions
- 拿到并同步state
代码放在https://github.com/yeatszhang/redux-tutorial, 须要装置gulp
代码是基于分支 v1.0.0-rc
api稍微有些区分,概况见 Breaking API changes for 1.0。
actionCreator
actions creator 是用来天生 action 的函数,在默许情况下能够吸收返回object
或许function
的函数,很多人进修flux的时刻把action与actionCreator弄殽杂….:
// 直接返回object
actionCreators.addTodo = function(text) {
return {
type: types.ADD_TODO,
text
};
}
// 返回函数
actionCreators.incrementAsync = function() {
return (dispatch, getState) => {
// actionCreator中能够经由历程getState取得当前的state
console.log(getState());
// 异步action
setTimeout(() => {
dispatch({
type: INCREMENT_COUNTER2,
});
}, 1000);
};
};
在没有运用任何 middleware
的情况下,只要这有两种 action
能够被 dispatch
。
app
在动态内容的最外层应当运用Provider举行包裹,provider吸收store作为参数,注重children是一个函数
并非reactElement
。provider
将store作为context往子节点举行通报,并完成store
的热替代。因此在provider内的组件实在能够不经由历程connect来拿到dispatch以及state,而直接经由历程context拿到store对象,不过作者不引荐这么做。
import React from 'react';
import { createStore, applyMiddleware, combineReducers } from 'redux';
// redux midlleware repositories
import thunk from 'redux-thunk';
// 将 redux 与 react 相干的部份,如 connector provider 零丁抽取出来
import { Provider } from 'react-redux';
import reducers from '../reducers';
import CounterApp from './CounterApp.js';
import logMiddleware from '../middleWares/logMiddleware.js';
const reducer = combineReducers(reducers);
const createStoreWithMiddleware = applyMiddleware(thunk, logMiddleware)(createStore);
const store = createStoreWithMiddleware(reducer);
// 运用middleWare thunk, 假如没有自定义中间层的需求能够直接写
// const store = createStore(reducer);
class App extends React.Component {
render() {
return (
<Provider store={store}>
{() => <CounterApp />}
</Provider>
);
}
}
smart component
smart component具有两个特性:
- 自动关联store中的state并自动re-render
- 能够经由历程dispatch来分发事宜,从而触发store的更新
刚打仗redux的同砚肯定会以为这个connect很难以明白。照样在代码内里说把。。。
/**
* Created by yichizhang on 15/7/26.
*/
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { Connector } from 'react-redux';
import Counter from '../components/Counter';
import actionCreators1 from '../actionCreators/actionCreators1.js';
import actionCreators2 from '../actionCreators/actionCreators2.js';
// state 是各reducer中state的鸠合
function select(state) {
// 从各reducer中挑选出component须要监听的state
return {
counter1: state.reducer1.counter,
counter2: state.reducer2.counter,
};
}
export default class CounterApp extends Component {
// select函数的返回值会与dispatch组装程一个object作为参数
// 从这里看出connector就是帮助拿到provider中store的dispatch要领以及挑选出须要运用的state
renderChild({ counter1, counter2, dispatch}) {
// 个人以为如许运用action非常不方便,尤其是当组件只须要触发actions不须要监听store的变化的时刻。我会偷懒经由历程context去拿到dispatch~~
const actions1 = bindActionCreators(actionCreators1, dispatch);
const actions2 = bindActionCreators(actionCreators2, dispatch);
const props = { ...actions1, ...actions2, counter1, counter2 };
// 一切的action以及state都邑以props的情势供应给Counter,然后在Counter内里就能够随心所欲了~
return <Counter {...props} />;
}
render() {
return (
<Connector select={select}>
{this.renderChild}
</Connector>
);
}
}
reducer
redux以为程序员不须要去写store中的逻辑而只须要写明对state的处置惩罚逻辑就好:
old sate => action => new state
这是一个完整同步的历程。reducer只须要声明初始状况以及state在吸收到action以后的转变划定规矩就能够了。
import React from 'react/addons';
import {INCREMENT_COUNTER1, DECREMENT_COUNTER1} from '../constants/actionsTypes.js';
const update = React.addons.update;
// state可所以任何范例
const initialState = {
counter: 0,
};
// reducer只是一个简朴的switch要领
export default function counter(state = initialState, action = null) {
switch (action.type) {
case INCREMENT_COUNTER1:
// 须要注重的是connector当select中的state发生变化时会做一个shallow equal的操纵,
// 所以假如须要操纵援用值的时刻肯定不能直接赋值,须要运用addon中的update或许immutable.js,晓得看到这两个东西又不想继承学了..实在很简朴
// 如许能够大大防止反复的render,从而进步机能
return update(state, {
counter: {
$set: state.counter + 1,
},
});
case DECREMENT_COUNTER1:
return update(state, {
counter: {
$set: state.counter - 1,
},
});
default:
return state;
}
}
middleWare
感兴趣的同砚能够看看,一般来说默许的thunk就够用了。我在例子里加了个log的中间层
// 打印触发的action
function logMiddleware() {
// 这里的next是下一个middleWare
return function(next) {
return function(action) {
// 打印此action并运用下一个middleWare处置惩罚该action
console.log(action);
next(action);
};
};
}
export default logMiddleware;
// 下面是默许的thunk middleWare
function thunkMiddleware(_ref) {
var dispatch = _ref.dispatch;
var getState = _ref.getState;
return function (next) {
return function (action) {
// 假如是函数则将dispatch与getState作为参数实行函数,不然交给写一个middleware处置惩罚
return typeof action === 'function' ? action(dispatch, getState) : next(action);
};
};
}
结语
实在redux不明白的处所直接看源码更好,redux的代码量很小而且构造也很清楚,发起人人都去看,不过作者貌似函数式编程的头脑很重,大批运用润饰器的语法,另有reduce~ 挺绕的~
以后会总结本身浏览redux源码的一些心得,以及各功能模块的完成道理~