从零开始搭建一个react项目开发(11)

Action Creators

Action creators 是创建acitons并传递给reducer的函数,它通常返回一个action对象,有时候借用thunk这样的中间件也可以返回dispatch多个actions,在我们的app中为了简化暂时不涉及这个模式。

function addItem(item){
 return {
  type: ADD_ITEM,
  item // this is new ES6 shorthand for when the key is the same as a variable or perameter within the scope of the object. It's the same as item: item
 }
}

Reducers

reducer是唯一可以触碰store的元素,初始值为initialState,形式上就是一个简单的switch语句,但是注意不能直接改变state,因为state是immutable。也就是说我们不能直接使用.pop or .push这些方法操作数组。

下面是示例代码:

const initialState = {
 list: []
};

export default function reducer(state = initialState, action){
 switch (action.type){
 case ADD_ITEM:
  return Object.assign(
   {},
   state,
   { list: [...state.list, action.item]} // here we see object.assign again, and we're returning a new state built from the old state without directly manipulating it
  )
 default:
  return state;
 }
}

概念已经介绍完毕,下面开始将原来的功能逻辑用redux重写。

1. Initial state

首先我们在 src/redux/modules/toDoApp中声明initialState。

const initialState = {
 list: [{item: 'test', done: false}] // just added this to test that state is being passed down propperly,
 newToDo: ''
};

export default function reducer(state = initialState, action){
 switch (action.type){
 default:
  return state;
 }
}

现在在 ToDoApp.js的 render() 方法中return之前添加console.log(this.props) 会打印出下面的对象:

toDoApp: Object
 list: Array[1]
  0: "test"
  length: 1
  __proto__: Array[0]
 __proto__: Object
__proto__: Object

测试通过,我们就可以传递这些数据给子组件了,这里就可以把原来List组件的 listItems prop和Input的value prop替换掉了。

<List
 onClick={this.onListItemClick}
 listItems={this.props.toDoApp.list}
 deleteListItem={this.deleteListItem}
/>
<Input
 value={this.props.toDoApp.newToDo}
 onChange={this.onInputChange}
 onSubmit={this.onInputSubmit}
/>

这里只是替换掉了数据,下面还需要把action也替换。

3. Input action

这个过程就是把我们原来在ToDoApp 组件的行为逻辑全部迁移到redux文件夹下的 toDoApp module中去。

const INPUT_CHANGED = 'INPUT_CHANGED';

export function inputChange(newToDo){
 return {
  type: INPUT_CHANGED,
  newToDo
 }
}

然后在reducer的switch中新增如下处理: