1. 程式人生 > >和我一起入坑-React-Native-加入Redux的TodoList

和我一起入坑-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