和我一起入坑-React-Native-加入Redux的TodoList
讀前須知
這個專案是第一次使用Redux的例項,並不具有專業性的理論知識。純粹分享一次開發過程與心得。之前寫了一篇沒有加入Redux的React Native ToDoList的小博文。這個專案也是在原來的基礎上進行裝修完成的。目的是為了體驗一下高深莫測的Redux。總之,在各位網友的友情支援下,我依然沒有看懂redux資料流的走向,勉勉強強通了一點。
(一)拆分結構
根據自己的習慣和固定套路,拆分目錄結構和元件結構。
├── public ├── todos-redux │ ├── actions │ │ └── index.js │ ├── components │ │ ├── todoItem.js │ │ └── todoList.js │ ├── containers │ │ ├── add.js │ │ ├── all.js │ │ ├── completed.js │ │ └── incomplete.js │ ├── reducers │ │ ├── index.js │ │ └── todos.js │ ├── store │ │ └── configureStore.js │ ├── utils │ │ └── utils.js │ ├── index.js │ ├── router.js
把react-navigation的導航元件集中放在router.js純粹是個人習慣。components中的元件是展示元件,不直接使用Redux。而containers中的是直接使用 Redux的元件。在這裡可以看成components是containers的子元件。
(二)程式碼實現
入口檔案
redux-persist是用來做redux的資料持久化。使用方法直接參考在GitHub上的基本示例。這裡的程式碼基本上都是固定套路。
// index.js import React, {Component} from 'react' import { Provider } from 'react-redux' import { TodosReduxStack } from './router' import { PersistGate } from 'redux-persist/integration/react' import configureStore from './store/configureStore' const { persistor, store } = configureStore() export default class TodolistRedux extends Component { render(){ return ( <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <TodosReduxStack /> </PersistGate> </Provider> ) } }
建立Action
// action/index.js
import Utils from '../utils/utils'
export const addTodo = (text) => {
return {
type: 'ADD_TODO',
id: Utils.uniqueId(),
content: text
}
}
export const toggleTodo = (id) => {
return{
type:'TOGGLE_TODO',
id
}
}
Reducers
// reducers/todos.js var initState = []; const todos = (state = initState, action)=>{ switch(action.type){ case 'ADD_TODO': return[ ...state, { id: action.id, content: action.content, completed: false } ] case 'TOGGLE_TODO': return state.map((t) => { if (t.id !== action.id) { return t } return Object.assign({},t,{completed:!t.completed}) }) default: return state } } export default todos
容器元件
connect()() 這個寫法叫函式的柯里化,漲知識啦。
// containers/all.js
const mapStateToprops = (state) => {
return {
todos: state.todos
}
}
const mapDispatchToProps = (dispatch) =>{
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
export default connect(mapStateToprops, mapDispatchToProps)(AllScreen)
使用filter函式過濾陣列,返回指定的值,這個地方有點雞肋哈,但是我不會其他的寫法了。
// containers/completed.js
const mapStateToprops = (state) => {
return {
todos: state.todos.filter(t => t.completed)
}
}
(三)使用Redux前後對比
沒有使用Redux之前,專案使用了React Native內建的DeviceEventEmitter方法。新增事項後要通知其他元件更新資料。還大量使用了AsyncStorage做資料的持久化,每一次的資料更新都需要用到它。如果是在稍複雜的專案中這樣寫,會死翹翹的!使用Redux 和 redux-persist 可以輕鬆實現這個功能,效果是明顯的。在已完成頁面將事項切換為未完成,該事項會直接消失,跑到未完成頁面中,這個地方並不需要做額外的處理。
說在後面的話
這種連個圖都沒有也沒有深入講解redux的文字都敢發出來,真的是表臉 (手動滑稽)。 完整的專案在這裡GitHub Todos Redux。