首頁 >web前端 >js教程 >如何透過react+redux升級版來實現todoList

如何透過react+redux升級版來實現todoList

亚连
亚连原創
2018-06-20 14:09:071623瀏覽

這篇文章主要介紹了react redux的升級版todoList的實現,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧

又是很久不寫博客了,最近在用螞蟻金服的ant-design-pro寫畢設,寫著寫著寫不下去了,很多東西都不理解,我不得不說大神寫出來的東西都是需要花學習成本的,或是底子好,對於React新手來說就有點難了。所以就老老實實的認真看了下Redux到底如何使用,在這裡推薦一下自己最近在看的書,寫的算是比較詳細的:《深入React技術棧》。廢話不多說,今天就分享下自己如何使用redux來實現一個todoList的,希望對想要用redux的你會有所幫助。

(為什麼叫升級版呢?因為之前寫過一個沒有用redux的todoList)

該項目使用react官方的create-react-app架構,每個目錄可以依照自己的需求來劃分。下面解釋下每個目錄的內容和功能。

public:主要放靜態資源(入口html文件,圖片資源,JSON檔案等);

src/component:不同的元件;

src/layouts:整個頁面的基本架構,主要是Nav,Footer,Content。 Nav裡面顯示User和Notice的數據,Content中實作頁面路由的切換,Footer固定不變;

src/redux:

--src/redux/configureStore:產生整個應用的store;

--src/redux/reducers:所有reducer的集合;

src/routes:頁面的整體路由;

src/utils:自己封裝的工具;

views:存放專案中所要展示的所有頁面;

index:整個專案的入口檔案;

二. 具體實作

1. 整個應用程式中store應儲存哪些資料?

const initialState = {
  taskListData: { //任务列表
    loading: false,
    error: false,
    taskList: [],
  }, 
  userData: { //用户信息
    loading: false,
    error: false,
    user: {},
  },
  noticeListData: { //通知列表
    loading: false,
    error: false,
    noticeList: [],
  },
  taskData: { //任务详情,在详情页使用
    loading: false,
    error: false,
    task: {},
  }
};

2. reducer的分佈:

每個state對應一個reducer,所以一共需要四個reducer,在src/redux/reducers中將所有的reducer合併,並且注意每個reducer的名字要和state同名:

/*redux/reducers.js*/
import { combineReducers } from 'redux';
import userReducer from '../component/User/indexRedux';
import noticeReducer from '../component/Notice/indexRedux';
import todoListReducer from '../views/TodoList/indexRedux';
import taskReducer from '../views/Detail/indexRedux';

export default combineReducers({
  userData: userReducer,
  noticeListData: noticeReducer, 
  taskListData: todoListReducer,
  taskData: taskReducer,
});

每個state都對應一個reducer,所以和state一樣,reducer應該在放在最頂級的父級組件的目錄中,所以將taskListData的reducer放在src/views/TodoList中,其他同理,程式碼如下:

/*views/TodoList/indexRedux.js*/
const taskListData = {
  loading: true,
  error: false,
  taskList: []
};
//不同的action;
const LOAD_TASKLIST = 'LOAD_TASKLIST';
const LOAD_TASKLIST_SUCCESS = 'LOAD_TASKLIST_SUCCESS';
const LOAD_TASKLIST_ERROR = 'LOAD_TASKLIST_ERROR';
const ADD_TASK = 'ADD_TASK';
const UPDATE_TASK = 'UPDATE_TASK';
const DELETE_TASK = 'DELETE_TASK';
function todoListReducer (state = { taskListData }, action) {
  switch(action.type) {
    case LOAD_TASKLIST: {
      return {
        ...state,
        loading: true,
        error: false,
      }
    }
    case LOAD_TASKLIST_SUCCESS: {
      return {
        ...state,
        loading: false,
        error: false,
        taskList: action.payload,
      };
    }
    case LOAD_TASKLIST_ERROR: {
      return {
        ...state,
        loading: false,
        error: true
      };
    }
    case UPDATE_TASK: {
      const index = state.taskList.indexOf(
        state.taskList.find(task => 
          task.id === action.payload.id));
      console.log(index);
      state.taskList[index].status = !state.taskList[index].status;
      return {
        ...state,
        taskList: state.taskList,
      };
    }
    case DELETE_TASK: {
      const index = state.taskList.indexOf(
        state.taskList.find(task => 
          task.id === action.payload.id));
      state.taskList.splice(index, 1);
      return {
        ...state,
        taskList: state.taskList,
      };
    }
    case ADD_TASK: {
      let len = state.taskList.length;
      let index = len > 0 ? len - 1 : 0;
      let lastTaskId = index !== 0 ? state.taskList[index].id : 0; 
      state.taskList.push({
        id: lastTaskId + 1,
        name: action.payload.name,
        status: false,
      });
      return {
        ...state,
        taskList: state.taskList,
      }
    } 
    default: {
      return state;
    }
  }
}
export default todoListReducer;

3. action creator的分佈:

每個動作都代表一個action,action由元件發出,所以將action creator單獨一個文件,放在元件目錄中。例如:ListItem元件的action creator:

/*ListItem/indexRedux.js*/
//处理更新任务状态后和删除任务后的taskList的状态;
const UPDATE_TASK = 'UPDATE_TASK';
const DELETE_TASK = 'DELETE_TASK';
//action creator,更新和删除任务
export function updateTask (task) {
  return dispatch => {
    dispatch({
      type: UPDATE_TASK,
      payload: task,
    });
  }
}
export function deleteTask (task) {
  return dispatch => {
    dispatch({
      type: DELETE_TASK,
      payload: task,
    });
  }
}


三. 如何將redux和元件連接

react-redux提供了connect方法,將state和action creator綁在元件上,然後在組價內部以props的方式取得。以下是TodoList頁面的具體實作:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import List from '../../component/List';
import { loadTaskList } from '../../component/List/indexRedux';
import { updateTask, deleteTask } from '../../component/ListItem/indexRedux';
import { addTask } from '../../component/SubmitDialog/indexRedux';
class TodoList extends Component {

  render () {
    return (
      <List {...this.props} />
    );
  }
}
export default connect( state => {
  return {
    loading: state.taskListData.loading,
    error: state.taskListData.error,
    taskList: state.taskListData.taskList,
  };
}, dispatch => {
  return {
    loadTaskList: bindActionCreators(loadTaskList, dispatch),
    updateTask: bindActionCreators(updateTask, dispatch),
    deleteTask: bindActionCreators(deleteTask, dispatch),
    addTask: bindActionCreators(addTask, dispatch),
  };
})(TodoList);

connect方法有四個參數,這裡主要說下前兩個參數:

(1)mapStateToProps:參數為state,回傳頁面所需要的所有state;

(2)mapDispatchToProps:參數為dispatch,傳回頁面所要使用的非同步回呼函數。

眼明手快的你肯定看到了,我們從redux套件中導出了bindActionCreators方法,該方法將dispatch和action creator綁定,用來觸發action。

四. 非同步的action creator如何觸發呢?

因為每個action creator都是非同步函數,我們傳給元件的只是函數的聲明,所以就要引入我們的中間件,只用在生成store時加入就行了:

/*redux/configureStore.js*/
import { createStore, applyMiddleware } from &#39;redux&#39;;
import thunk from &#39;redux-thunk&#39;;
import reducers from &#39;./reducers&#39;;
const initialState = {
  taskListData: {
    loading: false,
    error: false,
    taskList: [],
  }, 
  userData: {
    loading: false,
    error: false,
    user: {},
  },
  noticeListData: {
    loading: false,
    error: false,
    noticeList: [],
  },
  taskData: {
    loading: false,
    error: false,
    task: {},
  }
};
let enhancer = applyMiddleware(thunk);
let store = createStore(
  reducers,
  initialState,
  enhancer,
);
export default store;

在上面的程式碼中thunk就是一個中間件,我們將引入的中間件傳入applyMiddleware就可以了。

五. store在哪裡傳入元件呢?

我們一定會想到,store在整個應用程式中都存在,所以應該在整個應用程式的最頂層,對於一般專案而言,當然就是最頂端的路由了:

import React, { Component } from &#39;react&#39;;
import { BrowserRouter as Router, Route } from &#39;react-router-dom&#39;;
import { Provider } from &#39;react-redux&#39;;
import BasicLayout from &#39;../layouts&#39;;
import store from &#39;../redux/configureStore&#39;;
class RouterApp extends Component {
  render () {
    return (
      <Provider store={store}>
        <Router>
          <Route path="/" component={BasicLayout} />
        </Router>
      </Provider>
    );
  }
}
export default RouterApp;

Provider是react-redux的一個元件,作用就是用來將store傳入整個應用程式。

上面是我整理給大家的,希望今後對大家有幫助。

相關文章:

使用JS如何實作控制多個捲軸同步捲動

使用vue-cli webpack如何建立vue

如何使用JS編寫Ajax請求函數

#Chrome Firefox 自帶偵錯工具偵錯(詳細教學)

#有關Vue.js如何實現無限滾動載入

以上是如何透過react+redux升級版來實現todoList的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn