和我一塊兒入坑-React-Native-加入Redux的TodoList

讀前須知

這個項目是第一次使用Redux的實例,並不具備專業性的理論知識。純粹分享一次開發過程與心得。以前寫了一篇沒有加入Redux的React Native ToDoList的小博文。這個項目也是在原來的基礎上進行裝修完成的。目的是爲了體驗一下高深莫測的Redux。
總之,在各位網友的友情支持下,我依然沒有看懂redux數據流的走向,勉勉強強通了一點。react

(一)拆分結構

根據本身的習慣和固定套路,拆分目錄結構和組件結構。git

├── 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的子組件。github

(二)代碼實現

入口文件

redux-persist是用來作redux的數據持久化。使用方法直接參考在GitHub上的基本示例。這裏的代碼基本上都是固定套路。redux

// 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()() 這個寫法叫函數的柯里化,漲知識啦。segmentfault

// 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 能夠輕鬆實現這個功能,效果是明顯的。在已完成頁面將事項切換爲未完成,該事項會直接消失,跑到未完成頁面中,這個地方並不須要作額外的處理。ide

說在後面的話

這種連個圖都沒有也沒有深刻講解redux的文字都敢發出來,真的是表臉 (手動滑稽)
完整的項目在這裏GitHub Todos Redux函數

相關文章
相關標籤/搜索