@duanyubin
2016-03-20T15:50:58.000000Z
字数 3873
阅读 471
项目总结
state存放在一个唯一的store中state的唯一方法是,触发一个actionaction如何改变state需要依靠reducer
/*** 下方是reducer, 一个通过旧的`state`和已经触发的`action`生成新`state`的纯函数** `state`的形状由业务决定,可以是数组或者对象,**重要的是,不可以修改state对象,而是返回一个新的对象****/function counter(state = 0, action) {switch (action.type) {case 'INCREMENT':return state + 1case 'DECREMENT':return state - 1default:return state}}// 创建store用于存放整个app的所有state.// Its API is { subscribe, dispatch, getState }.let store = createStore(counter)// 可以手动订阅更新或者跟view层绑定store.subscribe(() =>console.log(store.getState()))// 触发actionstore.dispatch({ type: 'INCREMENT' })// 1store.dispatch({ type: 'INCREMENT' })// 2store.dispatch({ type: 'DECREMENT' })// 1
{type: ADD_TODO,payload: {text: 'Build my first Redux app'}}
function addTodo(text) {return {type: ADD_TODO,payload: {text}};}// 实际发送 actiondispatch(addTodo(text));function removeTodo(id) {return (dispatch, getState) => {return ajax().then((json) => {dispatch({type: REMOVE_TODO,id})})}}dispatch(removeTodo(id));
It provides a third-party extension point between dispatching an action, and the moment it reaches the reducer.
在dispatch一个action和此action到达reducer时,给第三方扩展提供切入点。
用于日志记录,异常处理,异步处理,路由等。


|-- actions|-- components|-- containers|-- middleware|-- reducers|-- routes|-- configureStore.js|-- index.jsx
负责与redux交流的一个react component
react-redux提供了 Provider元件和connect方法
用在应用的根元素外面,负责传递唯一的Store给应用
const reducer = combineReducers(reducers);const store = createStore(reducer);class App extends Component {render() {return (<Provider store={store}>{() => <App />}</Provider> );}}
- 将dispatch方法透过props的方式加到元件中
- 选取这个container需要state的哪一部分
import { increase, decrease}function mapStateToProps(state) {return { counter: state.counter };}function mapDispatchToProps() {return {increase: increase,decrease}}class CounterApp {render() {const { counter, dispatch } = this.props;return (<Counter counter={counter} /> );}}export default connect(mapStateToProps, mapDispatchToProps)(CounterApp)
before:
// users.scss@include foundation-button;@include foundation-forms;// detail.scss@include foundation-forms;
after:
// mian.scss:global {@include foundation-form-prepostfix;@include foundation-text-alignment;@include foundation-global-styles;....}// User.jsx<div styleName="wrap"><a className="button small" onClick={this.handleAddClick}>添加新用户</a></div>
// action.jsfunction requestCodes(id, pageNum = 1, dispatch) {// return ajax({ url: `http://localhost:3100/inviteCodes.json` })return ajax({url: `http://baoming.ws.netease.com/admin/invitecode/list`,body: { cid: id, pageNum }}).then((json) => {dispatch({type: type.REQUEST_CODES,data: json.data,id});return Promise.resolve(json);}).catch(errorHandler.bind(null, dispatch));}// 获取邀请码export function loadInviteCodes(id, pageNum) {return (dispatch) => {return requestCodes(id, pageNum, dispatch);};}// 获取邀请码总数export function fetchCodesCount(id) {return (dispatch) => {// return ajax({ url: `http://localhost:3100/count.json` })return ajax({url: `http://baoming.ws.netease.com/admin/invitecode/totalCount`,body: { cid: id }}).then((json) => {dispatch({type: type.REQUEST_CODES_COUNT,count: json.data});return Promise.resolve(json);});};}// errorHandlerimport * as modal from '../actions/modal';export default function errorHanlder(dispatch, fail) {dispatch(modal.error({ msg: `${fail.msg}` }));if (fail.code === -1 && window.location.hostname !== 'localhost') {setTimeout(() => {window.location.href = 'http://baoming.ws.netease.com/login/login';}, 500);}const error = new Error(fail);throw error;}
// before// action.jsfunction whatever() {if(confirm('something')){//....}}// after// action.jsfunction whatever(){modal.confirm('something').then((result) => {console.log(result)})}// modal.jsconst resolve = () => {}const reject = () => {}const promise = new Promise((res, rej) => {resolve = resreject = rej})function show() {}function hide(result) {resolve(result)}export function confirm(msg) {return promise}