# React and Redux

> view层发出actions通知触发store里的reducer从而来更新state；state的改变会将更新反馈给我们的view层，从而让我们的view层发生相应的反应给用户。

## 流程图

![pic-1](/_static/project/react.png)

## 目录结构

目录结构大概可以这样规划

```
app
  |_components
  |_reducers
  |_actions
  |_stores
    |_configureStores.js
  |_main.js
```

## 核心代码

举例核心代码。值得注意的是其中有一个state的传递有一些迷惑的地方，在下面的注释中可以找到思路。

### components
```js
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as CounterActions from '../../actions/counter.js';

class Counter extends Component {
  constructor() {
    super();
    this.state = {};
  }
  componentWillMount = () => {
    this.startCount();
  }
  startCount = () => {
    const { actions } = this.props;
    actions.listen('INC');
  }
  render() {
    return (
      <div>
        {this.props.counter.count}
      </div>
    );
  }
}
Counter.propTypes = {
  actions: React.PropTypes.object.isRequired,
  counter: React.PropTypes.object.isRequired
};
// 声明 connect 连接
// 将 redux 中的 state传给 App
function mapStateToProps(state) {
  return {
    counter: state.counter
  };
}
function mapDispatchToProps(dispatch) {
  const boundCounter = bindActionCreators(CounterActions, dispatch);
  return {
    actions: Object.assign({}, boundCounter)
  };
}
// 声明 connect 连接
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
```

### actions

action函数必须返回一个带有type属性的plain object。

```js
import * as constants from '../../constants/counter';
export function listen(type) {
  switch (type) {
    case 'INC':
      return {
        type: constants.INC
      };
    case 'DEC':
      return {
        type: constants.DEC
      };
  }
}
```

### reducers

reducer就是迎接action函数返回的线索的数据再处理函数，action是预处理函数。

```js
import {INC, DEC} from '../../constants/counter';
// 初始状态
const initState = {
  count: 1
};
// 定义转换的reducer函数
// action = {type: 'INC',counter: {count: 1}};
export default function start(state = initState, action) {
  switch (action.type) {
    case INC:
    // 对这个action做出响应
      state.count += 1 ; // 改变状态
      // return {count: 2} 返回给页面;
      return state;
    case DEC:
    // 对这个action做出响应
      state.count -= 1; // 改变状态
      // return {count: 0} 返回给页面;
      return state
    default:
      return state;
  }
}
```

```js
import { combineReducers } from 'redux';
import counter from './counter'; // {count: 2}返回给页面，所以页面用的是counter.count获取数据2
// 通过combineReducers将多个reducer合并成一个rootReducer:
const rootReducer = combineReducers({
  counter, // {count: 1}
  others
});
export default rootReducer;
```
