react-redux詳細使用方法@郝晨光

前言

這篇文章是之前我發表在CSDN上邊的,最近搬到簡書

文件目錄

    *---store   // 存放redux,數據,以及action
    
    *---store子目錄
        actions  // 存放action的文件夾
        reducers // 存放reducer的文件夾
        actionTypes.js // 存放所有的actionType
        index.js // store的入口文件

安裝

   npm install redux react-redux -S
   cnpm install redux react-redux -S
   yarn add redux react-redux -S

使用

  • 先在index.js中引入react-redux定義的Provider組件,并包裹在App組件外部
 import React from 'react';
 import ReactDOM from 'react-dom';
 import { Provider } from 'react-redux';
 import App from './App';
 
 ReactDOM.render(
     <Provider>
         <App />
     </Provider>,
     document.getElementById('root')
 );
  • 接著在store目錄下的index.js中創建一個store,并拋出
 import { createStore, combineReducers } from 'redux';
  // createStore方法是用來創建store的,combineReducers方法是用來合并多個reducer的
  
  // 創建根reducer,利用combineReducers合并多個reducer,此處還未定義reducer,所以暫空
  const rootReducer = combineReducers({
  
  })
  
  // 創建初始化的state,初始化為一個空對象即可,默認的數據建議都寫在reducer上
  const initializeState = {}; // 定義初始化的state
  
  // 創建store,第一個參數是根reducer,第二個參數可以是初始化的state,也可以是別的,暫且不提
  const store = createStore(rootReducer,initializeState);
  
  // 拋出store
  export default store;  
  • 在src/index.js中引入store,并且在Provider組件上使用
  /**之前的代碼**/
 import store from './store';
  
 ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
 );
  • 接著可以先定義數據,即定義reducer,在src/store/reducers目錄下,新建reducer,例如countReducer.js
  // 定義初始化的數據,根據實際數據即可
  const initializeState = {
      count: 1
  }
        
 // 定義reducer,第一個參數為state,賦予默認值為上邊定義的initializeState,
// 第二個參數為action,并return一個state  
 // 并且拋出這個countReducer
 export default function countReducer(state = initializeState,action) {
      return state;
 }
  • 在src/store/index.js中引入定義的countReducer,并合并到rootReducer中
 // 引入countReducer, 
 import countReducer from './reducers/countReducer';
       
 // 將countReducer合并到rootReducer上,并使用原有名稱
 const rootReducer = combineReducers({
      countReducer
 })
       
 // 也可以給countReducer改名,如下,改名成為count
 const rootReducer = combineReducers({
         count: countReducer
 })
  • 接著只需要將組件改造一下,就可以使用reducer上邊的數據了

  • 在src/APP.js中,或者是你需要使用store中數據的組件中,引入react-redux提供的connect方法

 import { connect } from 'react-redux';
  • 并且在拋出之前,定義獲取數據的方法mapStateToProps

      // 定義方法mapStateToProps,參數為state,并且返回一個對象,對象內定義需要獲取的store內的數據,
      // 由于是使用的countReducer中的數據,所以需要使用state.countReducer.屬性名 
      function mapStateToProps(state) {
           return {
               count: state.countReducer.count
           } 
      }
    
  • 接著,在拋出的時候調用connect方法改造當前組件

// connect的第一個參數為數據,即mapStateToProps方法
// 接著在第二個括號內傳入當前需要被改造的組件  
export default connect(mapStateToProps)(App);
  • 然后,我們在被改造的組件內就可以通過this.props.屬性名獲取store中的數據了,例如我在mapStateToProps方法中返回的是count數據,所以我在App組件中使用this.props.count即可
class App extends Component {
   render() {
       return (
           <div>
               {this.props.count}
           </div>
       );
    } 
}
  • 獲取到數據之后,接著應該是修改倉庫內的數據

  • 修改數據首先需要定義一個dispatch,在redux中,修改數據必須通過dispatch提交一個action來進行,在src/store/actions目錄下新建countAction.js

  • 在countAction.js中定義addCount方法,并return一個對象,對象上有一個type屬性,這個屬性對應的是一個常量字符串,這個字符串定義在src/store/actionTypes.js中,主要是為了可以公共的管理,因為同一個常量需要在兩個地方使用

 // countAction.js
 
 import { ADD_COUNT } from '../actionTypes'
 
 export function addCount() {
     return {
         type: ADD_COUNT
     }
 }
 
 // actionTypes.js
 
 export const ADD_COUNT = 'ADD_COUNT';
  • 接著在src/store/reducers/countReducer.js中,引入ADD_COUNT常量,并使用switch語句,或者if語句對action.type進行判斷,當觸發這個action的時候,讓當前這個reducer的state.count加一

        import { ADD_COUNT } from '../actionTypes';
    
        export default function countReducer(state = initializeState,action) {
            switch (action.type) {
                case ADD_COUNT:
                    return { count: state.count + 1 };
                default:
                    return state;
            }
        }   
    
  • 緊接著,要在組件中使用這個addCount方法,提交這個dispatch,觸發這個action

  • 在App.js或者是使用store的組件中,首先引入addCount方法,然后在mapStateToProps的下邊,在定義一個mapActionToProps方法,接著在connect的第二個參數位置,傳入這個方法即可

  • 在mapActionToProps方法中,第一個參數為dispatch,return一個對象,對象上定義方法
    方法名自定義即可,接著觸發這個方法的時候,觸發dispatch(),并傳入引入的addCount()方法,需要加括號調用,因為只有調用才會返回一個對象,( 或者addCount直接是一個對象,而不是一個函數 )

      import { addCount } from './store/actions/countAction'
      
      /** 其余代碼 **/
      
      /** mapStateToProps **/
      
      function mapActionToProps(dispatch) {
          return {
              addCount: () => dispatch(addCount())
          }
      }
      
      export default connect(mapStateToProps,mapActionToProps)(App);
    
  • 此時,可以在App組件內調用this.props.addCount()方法來修改store中的數據了

  • 當然,但凡是方法,都可以傳參,

  • 首先在src/store/actions/countAction.js中定義一個新的方法,

  • 當然,這個方法用到的REDUCE_COUNT常量要定義在src/store/actionTypes.js中

      // src/store/actions/countAction.js
      export function reduceCount(num) {
          return {
              type: REDUCE_COUNT,
              num
          }
      }
    
      // src/store/actionTypes.js
      export const REDUCE_COUNT = 'REDUCE_COUNT';
    
  • 而且,在src/store/reducers/countReducer.js中,需要通過switch進行判斷action,并執行操作

  • 由于我們在action中定義的對象的屬性是num,所以在reducer中進行參數使用的時候,也是使用action.num

  // src/store/reducers/countReducer.js
  import { ADD_COUNT, REDUCE_COUNT } from '../actionTypes'
  
  export default function countReducer(state = initializeState,action) {
      switch (action.type) {
          case ADD_COUNT:
              return { count: state.count + 1 };
          // 新增   
          case REDUCE_COUNT:
              return { count: state.count - action.num };
          default:
              return state;
      }
  }
  • 在App.js中使用reduceCount方法
 import { addCount, reduceCount } from './store/actions/countAction';

 /** 其余代碼 **/
 
 /** mapStateToProps **/
 
 function mapActionToProps(dispatch) {
     return {
         addCount: () => dispatch(addCount()),
         reduceCount: (num) => dispatch(reduceCount(num))
     }
 }
  • 接著在組件中直接調用this.props.reduceCount()方法,并傳入一個參數即可

  • 最后,為了遵循react的規范,我們需要在給組件定義props的時候,規定props的類型

  • 首先在App.js或者使用store的組件中,引入prop-types

  • 然后在文件最末尾,拋出之前,定義所有的props的類型

import PropTypes from 'prop-types';
 /** 其余代碼 **/
       
App.propTypes = {
   count: PropTypes.number.isRequired,
   addCount: PropTypes.func.isRequired,
    reduceCount: PropTypes.func.isRequired
}

最終代碼

index.js

 import React from 'react';
 import ReactDOM from 'react-dom';
 import { Provider } from 'react-redux';
 import store from './store';
 import App from './App';
 
 ReactDOM.render(
     <Provider store={store}>
         <App />
     </Provider>,
     document.getElementById('root')
 );

App.js

 import React, {Component} from 'react';
 import { connect } from 'react-redux';
 import { addCount, reduceCount } from './store/actions/countAction';
 import PropTypes from 'prop-types';
 
 class App extends Component {
     render() {
         return (
             <div>
                 <button onClick={()=>this.props.addCount()}>加1</button>
                 {this.props.count}
                 <button onClick={()=>this.props.reduceCount(5)}>減5</button>
             </div>
         );
     }
 }
 
 function mapStateToProps(state) {
     return {
         count: state.countReducer.count
     }
 }
 
 function mapActionToProps(dispatch) {
     return {
         addCount: () => dispatch(addCount()),
         reduceCount: (num) => dispatch(reduceCount(num))
     }
 }
 
 App.propTypes = {
     count: PropTypes.number.isRequired,
     addCount: PropTypes.func.isRequired,
     reduceCount: PropTypes.func.isRequired
 }
 
 export default connect(mapStateToProps,mapActionToProps)(App);

store/index.js

 import { createStore, combineReducers } from 'redux';
 import countReducer from './reducers/countReducer';
 
 const rootReducer = combineReducers({
     countReducer
 })
 
 const initializeState = {}; // 定義初始化的state
 
 const store = createStore(rootReducer,initializeState);
 
 export default store;

store/actionTypes.js

 export const ADD_COUNT = 'ADD_COUNT';
 export const REDUCE_COUNT = 'REDUCE_COUNT';

store/reducers/countReducer.js

 import { ADD_COUNT, REDUCE_COUNT } from '../actionTypes'
 
 const initializeState = {
     count: 1
 }
 
 export default function countReducer(state = initializeState,action) {
     switch (action.type) {
         case ADD_COUNT:
             return { count: state.count + 1 };
         case REDUCE_COUNT:
             return { count: state.count - action.num };
         default:
             return state;
     }
 }

store/actions/countAction.js

 import { ADD_COUNT, REDUCE_COUNT } from '../actionTypes'
 
 export function addCount() {
     return {
         type: ADD_COUNT
     }
 }
 
 export function reduceCount(num) {
     return {
         type: REDUCE_COUNT,
         num
     }
 }

- 如果需要使用中間件的話

  • 在store/index.js中,引入applyMiddleware,并使用在createStore的第三個參數位置
  • 接著引入需要使用的中間件,比如redux-thunk
  • 定義一個數組,用來存放所有的中間件
  • 在applyMiddleware方法中展開該數組即可
 import { createStore, combineReducers, applyMiddleware } from 'redux';
 // 引入redux-thunk
 import thunk from 'redux-thunk';

 // 定義中間件的數組
 const middleware = [ thunk ]

 // 使用
 const store = createStore(rootReducer,initializeState,applyMiddleware(...middleware));



結言
感謝您的查閱,代碼冗余或者有錯誤的地方望不吝賜教;菜鳥一枚,請多關照
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容