react-redux详细使用方法

文件目录

    *---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));

你可能感兴趣的:(javascript,React,react-redux)