在react專案中使用redux-thunk,react-redux,redux;使用總結
先看是什麼,再看怎麼用:
redux-thunk是一個redux的中介軟體,用來處理redux中的複雜邏輯,比如非同步請求;
redux-thunk
中介軟體可以讓action
建立函式先不返回一個action
物件,而是返回一個函式;
react-redux相當於一個適配react的一個redux外掛;redux本身可以在任何專案中使用,react-redux帶來了更適合react的方法;
而redux就是來管理資料的一個倉庫了。
核心概念是使用store來作為一個數據倉庫,所有元件都來通過資料來渲染檢視,react提供了資料到檢視的實時更新,這也就是react框架的命名來源吧;
redux中幾個關鍵詞;actionType,actionCreators,store,reducer: 這也是專案中劃分檔案的方式,將redux中每個功能劃分成單獨的檔案來管理,
使用redux流程,腦中要時時刻刻記住一張圖如下:
我們將所有需要管理的資料需要交給redux來管理,redux需要首先定義預設state放在reducers之中,而一般情況下元件會通過派發(dispatch)一個action來從store中獲取資料,store中儲存資料的地方是reducer.js;所以一般情況下會在reducer中return一個newState出來給store 而在元件中獲取store的資料的方法就需要訂閱(subscribe)store 這樣元件的state就會改變;
一般情況下的store資料夾裡分為reducer.js index.js constants.js(或者是actionType.js) 以及actionCreators.js
首先元件要獲取資料,會先建立一個action,這個action是一個物件,包含action的型別(就是actionType)和值 然後store去派發這個action,store接受到action之後會交給reducer.js來處理,這裡存放了預設資料和處理之後的資料,reducer處理好資料之後,返回一個新的state給store; 然後元件需要獲取這個新的state,一般情況是通過setState來獲取函式store; 設定當前元件的state; ;this.setState(store.getState())
而react-redux的作用是提供了 Provider元件來讓所有元件共享所有的狀態(官話:Provider提供的是一個頂層容器的作用);如下程式碼中 store作為一個屬性來給到provider 所有的元件都可以共享這個狀態,並且react-redux提供了connect 方法來連線mapStateToProps 、mapDispatchToProps 和元件
connect常見用法如下
const mapStateToProps = (state) => { return{ focused: state.getIn(['header','focused']), //從header 總的reducer裡面找focus的值 //focused: state.get('header').get('focused') list:state.getIn(['header','list']), page:state.getIn(['header','page']), mouseIn: state.getIn(['header','mouseIn']), totalPage:state.getIn(['header','totalPage']) } }
const mapDispatchToProps = (dispatch) => {
return{
handleInputFocus(list){
//console.log(list)
if(list.size === 0){
dispatch(actionCreators.getList())
}
dispatch(actionCreators.input_Focus())
},
handleInputBlur(){
dispatch(actionCreators.input_Blur())
},
handleMouseEnter(){
dispatch(actionCreators.mouseEnter())
},
handleMouseLeave(){
dispatch(actionCreators.mouseLeave())
},
handleChangePage(page,totalPage){
console.log(page,totalPage)
if(page<totalPage){
dispatch(actionCreators.ChangePage(page+1))
}else{
dispatch(actionCreators.ChangePage(1))
}
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(Header); //連線Header元件和mapStateToProps,mapDispatchToProps
<Provider store={store}> <div> <Globalstyle/> <Header/> <BrowserRouter> <div> <Route path='/' exact redirect='/home' component={Home}/> <Route path='/detail' component={Detail}/> </div> </BrowserRouter> <Globalstyleicon/> </div> </Provider>
通常情況下,我們的專案可能會有龐大的資料,所以一般情況下會將store單獨拆分到每個元件之中,這個時候就需要我們來使用combineReducers 來連線所有的狀態;
import {combineReducers} from 'redux-immutable'
通常情況下總的reduce程式碼如下
import {combineReducers} from 'redux-immutable' //讓生成的資料是immutable資料內容 import {reducer as headerReducer} from '../common/header/store' //從header元件的reducer中引入reducer來結合 const reducer = combineReducers({ header:headerReducer }) export default reducer
同時,我們的state資料不能隨便改變,這個時候就需要引入immutable來對資料進行管理(某個部落格這樣寫的:
JavaScript 中的物件一般是可變的(Mutable),因為使用了引用賦值,新的物件簡單的引用了原始物件,改變新的物件將影響到原始物件。如 foo={a: 1}; bar=foo; bar.a=2
你會發現此時 foo.a
也被改成了 2
。雖然這樣做可以節約記憶體,但當應用複雜後,這就造成了非常大的隱患,Mutable 帶來的優點變得得不償失。為了解決這個問題,一般的做法是使用 shallowCopy(淺拷貝)或 deepCopy(深拷貝)來避免被修改,但這樣做造成了 CPU 和記憶體的浪費。
)
immutable中常用的方法:
1:fromJS 把一個普通物件改變成一個immutable物件
2:set immutable物件的set方法,會結合之前immutable物件的值和設定的值,返回一個新的物件 使用如下: state.set('focused',true);
3:get : get() 、 getIn() 可以用來獲取資料 如下使用: state.getIn(['header','list']) 等價於state.get('header').get('focused')
4:merge(淺合併,新資料與舊資料對比,舊資料中不存在的屬性直接新增,就資料中已存在的屬性用新資料中的覆蓋)
merge使用如下:
state.merge({
list:action.data,
totalPage:action.totalPage
})
我的程式碼倉庫:https://github.com/qiaoqiao10001