Todo
你有想过,为什么todo demo这么受欢迎吗? 因为它涉及到数据的增删改查,组件化等方方面面。 在学习redux的过程中,对于单一data flow,todo是个完美的例子,我们会在接下来的实例中一点点完善我们的todo,并引入相关概念与API。
主要功能
- 输入框输入内容,点击按钮添加todoItem并展示
- 点击todoItem,todoItem被标记为completed,表现为文字出现横划线
- 点击切换按钮可以查看不同状态下的todoItem,分别为:
ALL
,ACTIVE
,COMPLETED
接下来我们将从最基本的功能实现起,至于为什么不一步到位,在下面的例子中会进行解释,相信你会明白这样的好处。
I. Implement basic & rough reducer of todos
- 考虑到state里的第一项将是存放所有todoItem的Array,其初始状态应该是一个empty array.
- Action type: 根据功能可知,我们会涉及的action有: 'ADDTODO' ,'TOGGLE_TODO‘
/**
* todos -> reducer
* @param [Array] array for todoItems
* @param [Object] action for operate todoItem
* @return [Array] the result of updated state
*/
const todos = (state = [], action) => { // Initial state will be an empty array
switch (action.type) {
case 'ADD_TODO':
return [
...[state],
{
id: action.id,
text: action.text,
completed: false
}
]
case 'TOGGLE_TODO':
return state.map( t => t.id === action.id ?
{...t, completed: !action.completed} : t)
default:
return state
}
}
II. Implement Todo component && createStore
由于我们已经实现过,这里我们直接使用redux提供的createStore
.
const { createStore } = Redux
const store = createStore(todos)
/**
* Todo -> Component
* @param [String] text, content of todoItems
* @param [Boolean] status, decide which state to show
*/
const Todo = ({text, status}) => (
<div style={{border: '1px solid #ccc', display: 'inline-block', padding: 10, margin: 10}} >
<p style={{margin: 0}}>{`content: ${content}`}</p>
<p style={{margin: 0}}>{`status: ${status}`}</p>
</div>
)
III. Implement render function && subscribe render to store
const render = () => {
ReactDOM.render(
<div>
{store.getState().map( todo => {
let status = todo.completed ? 'yes' : 'no'
return (
<div>
<Todo
key={todo.id}
content={todo.text}
status={status}
/>
</div>
)
})}
</div>
,
document.getElementById('root')
)
}
store.subscribe(render)
IV. dispatch action
store.dispatch({
type: 'ADD_TODO',
id: 0,
text: 'Learn React'
})
store.dispatch({
type: 'ADD_TODO',
id: 1,
text: 'Learn Redux'
})
store.dispatch({
type: 'ADD_TODO',
id: 2,
text: 'Learn React-Router'
})
看看效果:
测试一下toggle:
store.dispatch({
type: 'TOGGLE_TODO',
id: 0
})