您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“如何實(shí)現(xiàn)react+redux的升級(jí)版todoList”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“如何實(shí)現(xiàn)react+redux的升級(jí)版todoList”這篇文章吧。
結(jié)構(gòu)
該項(xiàng)目使用react官方的create-react-app架構(gòu),每個(gè)目錄可以根據(jù)自己的需求來(lái)劃分。下面解釋下每個(gè)目錄的內(nèi)容和功能。
public:主要放靜態(tài)資源(入口html文件,圖片資源,JSON文件等);
src/component:不同的組件;
src/layouts:整個(gè)頁(yè)面的基本架構(gòu),主要就是Nav,F(xiàn)ooter,Content。Nav里面顯示User和Notice的數(shù)據(jù),Content中實(shí)現(xiàn)頁(yè)面路由的切換,F(xiàn)ooter固定不變;
src/redux:
--src/redux/configureStore:生成整個(gè)應(yīng)用的store;
--src/redux/reducers:所有reducer的集合;
src/routes:頁(yè)面的整體路由;
src/utils:自己封裝的工具;
views:存放項(xiàng)目中所要展示的所有頁(yè)面;
index:整個(gè)項(xiàng)目的入口文件;
二. 具體實(shí)現(xiàn)
1. 整個(gè)應(yīng)用中store中應(yīng)存儲(chǔ)什么數(shù)據(jù)?
const initialState = { taskListData: { //任務(wù)列表 loading: false, error: false, taskList: [], }, userData: { //用戶信息 loading: false, error: false, user: {}, }, noticeListData: { //通知列表 loading: false, error: false, noticeList: [], }, taskData: { //任務(wù)詳情,在詳情頁(yè)使用 loading: false, error: false, task: {}, } };
2. reducer的分布:
每個(gè)state對(duì)應(yīng)一個(gè)reducer,所以一共需要四個(gè)reducer,在src/redux/reducers中將所有的reducer合并,并且注意每個(gè)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, });
每個(gè)state都對(duì)應(yīng)一個(gè)reducer,所以和state一樣,reducer應(yīng)在放在最頂級(jí)的父級(jí)組件的目錄中,所以將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的分布:
每個(gè)動(dòng)作都代表一個(gè)action,action由組件發(fā)出,所以將action creator單獨(dú)一個(gè)文件,放在組件目錄中。例如:ListItem組件的action creator:
/*ListItem/indexRedux.js*/ //處理更新任務(wù)狀態(tài)后和刪除任務(wù)后的taskList的狀態(tài); const UPDATE_TASK = 'UPDATE_TASK'; const DELETE_TASK = 'DELETE_TASK'; //action creator,更新和刪除任務(wù) 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綁在組件上,然后在組價(jià)內(nèi)部以props的方式獲取。下面是TodoList頁(yè)面的具體實(shí)現(xiàn):
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方法有四個(gè)參數(shù),這里主要說(shuō)下前兩個(gè)參數(shù):
(1)mapStateToProps:參數(shù)為state,返回頁(yè)面所需要的所有state;
(2)mapDispatchToProps:參數(shù)為dispatch,返回頁(yè)面所要使用的異步回調(diào)函數(shù)。
眼明手快的你肯定看到了,我們從redux包中導(dǎo)出了bindActionCreators方法,該方法將dispatch和action creator綁定,用來(lái)觸發(fā)action。
四. 異步的action creator如何觸發(fā)呢?
因?yàn)槊總€(gè)action creator都是異步函數(shù),我們傳給組件的只是函數(shù)的聲明,所以就要引入我們的中間件,只用在生成store時(shí)加入就行了:
/*redux/configureStore.js*/ import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import reducers from './reducers'; 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就是一個(gè)中間件,我們將引入的中間件傳入applyMiddleware就可以了。
五. store在哪里傳入組件呢?
我們肯定會(huì)想到,store在整個(gè)應(yīng)用中都存在,所以應(yīng)該在整個(gè)應(yīng)用的最頂層,對(duì)于一般項(xiàng)目而言,當(dāng)然就是最頂端的路由了:
import React, { Component } from 'react'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import { Provider } from 'react-redux'; import BasicLayout from '../layouts'; import store from '../redux/configureStore'; class RouterApp extends Component { render () { return ( <Provider store={store}> <Router> <Route path="/" component={BasicLayout} /> </Router> </Provider> ); } } export default RouterApp;
Provider是react-redux的一個(gè)組件,作用就是用來(lái)將store傳入整個(gè)應(yīng)用。
以上是“如何實(shí)現(xiàn)react+redux的升級(jí)版todoList”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。