如下文章均爲我的近期所學心得,自學react、redux,逐漸找到本身的方向,現將本身的方向方式寫出來,以供你們學習參考,確定會有不足,歡迎批評指正。react
平常項目直接使用react是徹底沒有問題的,但是隨着項目的日益壯大,組件數量的逐漸增加,組件之間的嵌套使得數據的管理愈來愈繁重。
純react項目,每一個組件本身維護本身的state,父子組件之間通訊、兄弟組件通訊也均可以作到,只不過隨時項目代碼量的增長後期會變得難以維護,因此使用redux這種數據管理是頗有必要的,並且也是自我技術水平提升的一個很好方向。ajax
本文專一功能實現、使用流程,因此可能細節問題點闡述的不夠深,不過我的以爲用於初學者使用而且達到想要的功能應該能夠知足了。redux
首先原理(純白話):
頁面操做(點擊啊什麼的)觸發action -->
action作一層處理後觸發reducer -->
reducer中定義全局的惟一的store中的state+存入的方法(必須是純函數,也就是說你傳入什麼參數就輸出相應的結果,不能夠根據實時時間戳啊等相似的方法產出不一樣的值。) -->
最後數據保存進了store中的state,頁面也會根據state的改變自動更新。後端
基本: Provider:具體概念不贅述,想細研究的自行度娘,這裏只說明放在根組件的最外層並將store傳遞進去 <Provider store={store}> <Component /> </Provider>
代碼(登陸功能流程):session
// 使用react-redux中的connect方法 import { connect } from 'react-redux'; // 導入咱們定義的action import { saveUserinfo } from '@/Reducers/Pages/actions'; // 使用connect包裹咱們的state和action,這裏有兩個方法(mapStateToProps、mapDispatchToProps),具體概念自行度娘 // 組件結尾導出處 export default connect(mapStateToProps, mapDispatchToProps)(Login); // 能夠寫成 export default connect(state => ({ // 若是你的組件須要使用store中的state,就在這裏引入你因此要使用的reducer函數名 }), { // 這裏引用你當前組件所須要使用的全部action方法 saveUserinfo })(Login); // 按鈕提供一個點擊事件 <button onClick={this.sumitForm}>登陸</button> // sumitForm方法 sumitForm = () => { var username = this.refs.username.value; var password = this.refs.password.value; // 發送ajax請求,這裏我封裝一層,很簡單,能夠直接寫ajax請求,主要點在請求成功的回調裏 LoginFunc(username,password) .then(res => { // 請求成功後的數據 var data = res.data; // 這裏就是觸發action的地方,只須要將咱們須要的數據做爲參數傳進去就好 this.props.saveUserinfo(data); this.props.history.push("/index"); }) }
以上就是咱們在組件中觸發action的過程,到這裏你就能夠將接口返回來的數據傳遞給action了app
// 定義action時須要先定義action-type,做用就是關聯action和reducer,action想要觸發reducer那麼只須要使用定義的type就能夠,不須要去引用reducer,這樣別人在看咱們的代碼時,看type就知道這一塊有哪些功能了,具體的註釋也能夠寫在type中。 // type很簡單 // 保存用戶信息 export const SAVEUSERINFO = "SAVEUSERINFO";
action代碼ide
// 導入type import * as Pages from './action-types'; // 保存用戶表單數據 export const saveUserinfo = (data) => { // 這個傳進來的data就是咱們剛剛在組件中傳遞進來的後端返回數據 // 這裏直接returntypes,並將data傳遞過去 return { type: Pages.SAVEUSERINFO, data } }
這裏就是action,咱們能夠將組件中的後端請求寫在action裏,只須要返回的時候觸發type並將數據傳遞過去就好函數
下面咱們看reducer學習
// 以前說了,action只須要觸發type就能夠觸發reducer了 // 因此reducer中一樣須要引入reducer import * as Pages from './action-types'; // 在reducer中咱們須要定義state,也是就是惟一store中的state let defaultValue = { session_id: "", user_name: "", user_id: "", is_login: false, initialization: "", org_name: "" } // reducer中就是將action傳遞過來的數據保存到store中的state裏 // 兩個參數,第一個是state,第二個是action傳遞過來的數據,包含type和數據,經過type值判斷執行那個函數,這裏只定義了一個type export default function UserInfo (state = defaultValue, action = {}) { switch (action.type) { // 這個就是type也就是action和reducer關聯的type case Pages.SAVEUSERINFO: return { ...state, // 這裏就是將action傳遞過來的數據保存到咱們的store中 ...{ session_id: action.data.data.session_id, user_name: action.data.data.name, user_id: action.data.data.id, is_login: true, initialization: action.data.data.initialization, org_name: action.data.data.org_name } }; default: return state; } }
以上就完成了咱們從後端拿數據,保存到store中的全部流程。this
// 保存到了store中後,咱們頁面的全部組件均可以拿這裏邊的數據, // 一樣,咱們組件中用到數據的地方會根據store中數據的改變而改變,也就是說咱們想要改變頁面的狀態,惟一的辦法就是觸發action完成以上步驟。
到這裏咱們尚未結束,須要咱們造成閉環,也就是怎麼將store存入咱們的Provider
// 我這裏是將store拆分了,按功能去拆分的,具體能夠看每一個人的習慣去拆分
個人目錄結構,可根據具體項目區自定本身的目錄結構
// 有拆分就要有合併,因此咱們要在存入Provider以前進行reducer的合併 // 這裏使用redux提供的方法combineReducers import { combineReducers, } from 'redux'; import UserInfo from './Pages/reducers'; const rootReducer = combineReducers({ UserInfo, // 一些其餘功能的reducer // UserStaffDirectory, // addUserMsgReducer }); // 導出統一的reducer export default rootReducer;
插一句,以上就已經完成了基本功能,這裏我在多加一項功能,就是數據持久化,也就是咱們數據存到store中可是會存在一個刷新數據丟失的問題,這樣很不利與咱們項目的使用,因此我加入一個新的庫,來保證咱們的數據是可持久化的,這裏使用redux-persist庫
數據持久化
// 首先導入redux的一些方法 import { createStore, applyMiddleware } from 'redux'; // 還使用了thunk,還沒來的及去研究,這裏先使用吧 import thunk from 'redux-thunk'; // 引入redux-persist import { persistStore, persistReducer } from 'redux-persist'; import { PersistGate } from 'redux-persist/es/integration/react'; import storage from 'redux-persist/es/storage' // 首先定義一個對象(按官方文檔來的,沒具體研究) const persistConfig = { key: 'root', storage, }; // 將咱們的合併後的reducer引入 import Reducers from '@/Reducers'; // 使用redux-persist合併 const persistedReducer = persistReducer(persistConfig, Reducers) // 定義一個函數,返回persistor和store,讓個人組件使用 function configureStore(){ // 這裏我使用了thunk,具體原理我也沒去細研究,使用redux的createStore去合併,最終產出咱們須要傳入Provider的store let store = createStore(persistedReducer, applyMiddleware(thunk)); // 這裏就是應用redux-persist以完成數據持久化 let persistor = persistStore(store); return { persistor, store } } // 組件render中 const render = Component => { // 引入 const { persistor, store } = configureStore(); ReactDOM.render( // 將store傳入跟組件 <Provider store={store}> // 數據持久化 <PersistGate persistor={persistor}> // 全部子組件 <Component /> </PersistGate> </Provider>, document.getElementById('app'), ) }
以上就完成了所有循環,組件發起action,觸發reducer,保存數據到store中,組件被更新。
只有存的步驟,不能沒有取,對吧,上文中實現了登陸功能,而且將後端返回的數據保存到store中,如今咱們將store中的數據拿出來展現在界面上。
登陸請求成功後後端會返回用戶名,用戶ID等信息,咱們已經將其保存到了store中,下面看咱們的header組件將引用咱們store中的用戶名。
不須要咱們引入過多的文件,只須要在組件結尾處的方法mapStateToProps加入咱們要的reducer函數名便可
const mapStateToProps = state => ({ UserInfo: state.UserInfo }) export default connect(mapStateToProps,({}))(Header); // 組件中使用 this.props.UserInfo.user_name // 便可取值 // 同時呢,咱們改變了store中的user_name那麼咱們取值的地方也會動態更新。
以上就是本文所有內容,若有發現不足,或錯誤之處,煩請指正。轉載請註明出處,SF大洋首發。