react-redux使用小結 react-redux store reducer action 整合storereduceraction 補充 使用redux-dev-tools 讓改變reducer後能夠即時重新整理頁面 總結
需要使用的庫redux,react-redux,react-router-redux react-redux
使用一個react-redux 的庫使得redux的使用更簡潔,它提供了provider和connect方法
先在入口檔案內使用
<Provider store={store}> <組件/> </provider>
1 2 3
store
這裡使用了redux中的重要組成部分store,所以下面先說store的檔案構成 把所有資料取出,如果是靜態就引入json檔案,如果是動態就使用fetch或者ajax載入,來自服務端的 state 可以在無需編寫更多代碼的情況下被序列化並注入到用戶端中,在開發中使用本地的json資料可以加速開發 然後使用redux庫中的createStore把reducer和上一步的資料執行個體化出一個store,eg:const store = createStore(rootReducer, defaultState);
這樣最簡單的store就做好了,然後上面還有reducer需要處理 reducer
reducer的簡單作用就是根據action的不同跟新state,此處的更新必須是返回一個新的state,而不是在原來的state上做修改
例如:實現一個增加評論和刪除評論的功能
//注意此處傳的參為state和actionlet postComments = (state = [], action) => { switch (action.type){ case "ADD_COMMENT": return [ ...state, //原來的state { user: action.author,增加的state text: action.text } ]; case "REMOVE_COMMENT": return [ ...state.slice(0,action.i), //剔除數組中需要刪除的那個 ...state.slice(action.i + 1) ]; default: return state; }};
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
在我們的項目中,我們可能會分模組和功能寫多個reducer檔案,但最終,我們都需要把它合并到一個裡面,這需要使用redex中的combineReducers
import { combineReducers } from "redux";import * as reducers from "./reducers"const rootReducer = combineReducers({ ...reducers});export default rootReducer;
1 2 3 4 5 6
這是通用的用法,而在我學習的視頻中,他在combineReducers中還加上了routerReducer,它的具體作用可以看官方文檔react-router-redux,反正我是沒怎麼看懂,具體的作用感覺就是在切換頁面的時候會多出一個LOCATION_CHANGE的時間,可以用來追蹤頁面的變化,具體要使用的話需要更改3個檔案, 上面的合并reducers的檔案,在引入react-router-redux庫的routerReducer方法後,在combineReducers中加上routing: routerReducer 在store.js中加上以下代碼
...import { syncHistoryWithStore } from 'react-router-redux';import { browserHistory } from 'react-router';...export const history = syncHistoryWithStore(browserHistory, store);
1 2 3 4 5
3.在主入口檔案中的<Router>根路由標籤使用store.js中匯出的history
<Router history={history}>...<Router>
1 2 3
action
action我把它做是一個介面,它主要是和reducer聯動的,它預設必須返回一個type,用這個type的值來判斷reducer中做哪一步操作
例如:我需要增加一個評論,那我需要傳評論文章的id,評論的使用者,評論的內容,所以定義如下
// add commentexport let addComment = (postId, author, text) => { return { type: 'ADD_COMMENT', postId, author, text }};
1 2 3 4 5 6 7 8 9
整合store,reducer,action 我們的store已經在provider裡面傳入了,但我們provider內的組件不能直接使用,要使用就必須是connect過的組件,這方面的介紹在React 實踐心得:react-redux 之 connect 方法詳解這篇文章裡有詳細說明 store.js裡面我們就把reducer和store的資料進行執行個體化了,會建立出store的幾個預設方法dispatch(),getState(),subscribe() 缺少的1、是組件能夠調用store內的資料;2、通過store提供的dispatch函數將action發送到reducer,reducer通過一個switch函數處理資料,reducer將資料提供給store,更新state,組件自動重新整理
以上還未解決的問題就用connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])來解決,這裡我們只使用第一和第二個參數
import { bindActionCreators } from 'redux';import { connect} from 'react-redux';//此處傳入的state即為store中的defaultStatelet mapStateToProps = (state) => { return{ posts: state.posts, comments: state.comments }};//此處的actionCreators即為簡單的action檔案//Redux 本身提供了 bindActionCreators 函數,來將 action 封裝成直接可被調用的函數let mapDispatchToProps = (dispatch) => { return bindActionCreators(actionCreators, dispatch);};//最後調用connect()const App = connect(mapStateToProps, mapDispatchToProps)(Main);export default App;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
補充
使用redux-dev-tools
要使用redux的調試工具需要在store.js檔案中的createStore()步驟中加入第三個參數,enhancers
import { createStore, compose} from 'redux';//redux-dev-toolsconst enhancers = compose( window.devToolsExtension ? window.devToolsExtension() : f => f);const store = createStore(rootReducer, defaultState, enhancers);
1 2 3 4 5 6 7
讓改變reducer後能夠即時重新整理頁面
webpack可以監聽我們的組件變化並做出即時相應,但卻無法監聽reducers的改變,所以在store.js中增加一下代碼
//此處accepts的參數是reducers的存放路徑,require()內的路徑為執行combineReducers()的檔案if(module.hot){ module.hot.accept("./reducers/", () => { const nextRootReducer = require('./reducers/index').default; store.replaceReducer(nextRootReducer); })}
1 2 3 4 5 6 7
總結
經過一次回顧後,感覺比之前只看這視屏照著打要理解得更加深刻,雖然還是會有部分不能融會貫通,但基本的流程是清楚了不少,感覺果然向阮一峰老師的博文中指出使用react很方便,但是redux就不是一定要選擇用的,因為它還是存在一定的難度和複雜度的,特別是本身的商務邏輯不多,程式不大的時候
以下貼出其餘不錯的關於介紹redux和react的相關文章
React Redux作用流程