- TodoList
- 1. 編寫actions.js
- 2. 分析state
- 試著拆分成多個reducer
- 3. 了解store
- 4. 了解redux數據流生命周期
- 5. 分析容器組件和展示組件
- 搞清楚,數據到底是如何流動的?
- 6. 編寫展示組件的代碼
- 7. 編寫容器組件
- 8. 傳入store
- 9. 總結
- 10. 參考
TodoList
腳手架Github地址
1. 編寫actions.js
2. 分析state
試著拆分成多個reducer
3. 了解store
store.getState()
store.dispatch(action)
store.subscribe(listener)注冊監聽器
調用store.subscribe(listener)返回的函數來注銷監聽器
4. 了解redux數據流生命周期
store.dispatch(action);
- store調用傳入的reducer。
- 根reducer將多個子reducer輸出的state合成一個單一的state樹。
- store保存了根reducer返回的state樹。
5. 分析容器組件和展示組件
在這里,我遇到了很多問題。展示組件就沒有什么好說的了,主要是容器組件。
搞清楚,數據到底是如何流動的?
下面舉例:
- React組件上有一個點擊事件。
- 當點擊之后,點擊事件對應一個dispatch(actionCreator())。
- store會將actionCreator()返回的action以及當前的state傳遞給reducer。
- reducer收到action,然后根據action.type更新state,并且返回新的state。
- store保存新的state。
- state更新后,組件調用render()方法。
那么問題來了:
由于展示組件,沒有數據,那么數據該是如何來的?
回答:數據是從存放在state里的,如何將state里的數據,傳遞給展示組件呢?使用connect()函數,它接受兩個參數,兩個參數分別是函數。
function mapStateToProps(state) {return {todos: selectTodos(state.main.todos, state.main.visibilityFilter),visibilityFilter: state.main.visibilityFilter,};
}function mapDispatchToProps(dispatch) {return {onAddClick: text => dispatch(addTodo(text)),onFilterChange: nextFilter => dispatch(setVisibilityFilter(nextFilter)),};
}class Main extends Component { render() { return ( <AddTodo onAddClick={this.props.onAddClick} /> <VisibleTodoList /> <Footer onFilterChange={this.props.onFilterChange} visibilityFilter={this.props.visibilityFilter} /> ); } } Main.propTypes = { onAddClick: PropTypes.func.isRequired, onFilterChange: PropTypes.func.isRequired, visibilityFilter: PropTypes.oneOf([ 'SHOW_ALL', 'SHOW_ACTIVE', 'SHOW_COMPLETED', ]); }; export default connect(mapStateToProps, mapDispatchToProps)(Main);
- 上面的demo,是將Main作為一個展示組件。
- 將
mapStateToProps
和mapDispatchToProps
注入到Main
里。 - 所以在
Main
組件里,就可以使用注入的方法和屬性了。 - 值得注意的地方,在Main里使用的props都要進行檢測,也就是下面的
Main.propTypes
。 - 除了將注入和組件寫在一個js文件里,還可以將它們分開寫。
- 就比如VisibleTodoList和TodoList分別寫。然后將2個函數注入到TodoList里去。
- 對了,初始化的state是寫在reducer里的,因為無論如何都會去調reducer。
在做的過程中,我還遇到了一個問題,它在幾個地方三番五次的阻撓我。
// 代碼里,我是這么獲取state的數據的。
state.todos:
state.visibleFilter;// 但是事實上,使用的腳手架里,它對app包了一層路由,它在最外層的reducer里的代碼是這樣的。
import main from 'containers/Main/reducer'; export default function createReducer(asyncReducers) { return combineReducers( main, routing: routerReducer, ...asyncReducers, ); } // 所以我本身拿到的state是包含了main和routing這兩個對象的。因此我要拿我組件里的state的數據,應該下面這樣: state.main.todos; state.visibleFilter;
6. 編寫展示組件的代碼
- class類
- 每個組件都要對propTypes進行驗證
- 要export
7. 編寫容器組件
- 定義
mapStateToProps()
將當前的state映射到組件的props, 讀取state操作。 - 定義
mapDispatcherToProps()
, 分發action操作。
- 傳入dispatch方法。
- 返回期望注入到展示組件的props中的回調方法。
- 回調方法里,可以分發action。
-
使用connect()方法。
export default const VisibleTodoList = connect(mapStateToProps,mapDispatcherToProps, )(TodoList); // TodoList為要被注入的展示組件
8. 傳入store
使用React Redux里的Provider組件,將store注入到Provider組件,它可以讓所有容器組件都可以訪問到store。
9. 總結
當我遇到問題:
- 要沉著冷靜。
- 要管理好時間。
- 別被bug或error搞的不高興,要高興,又有煅煉思維的機會了。
- 要思考這是為什么?
- 要搞清楚問題的本質。
- 要探究問題,探究數據的流動。
10. 參考
React中文文檔
Github地址