Administrator
发布于 2020-07-24 / 7451 阅读 / 0 评论 / 0 点赞

react-redux使用方法

react-redux使用方法

redux简介

  1. 什么的redux?

    官方解释:redux 是 js 应用的可预测状态的容器。 可以理解为全局数据状态管理工具(状态管理机),用来做组件通信等。

    在react-redux里面,可以把它理解成vue里面的全局状态管理机制vuex

  2. 为什么使用redux?

image

  1. state

    前端中的state就是数据,就是一个对象。redux中的state是不能直接修改的,只能通过action来修改,相当于我们在单例中定义setter方法。

  2. action

    redux 将每一个更改动作描述为一个action,要更改state中的内容,你需要发送action。一个action是一个简单的对象,用来描述state发生了什么变更。

    const INCREMENT = 'INCREMENT'
    const incrementAction = {"type": INCREMENT, "count": 2}
    
  3. reducer

    数据state,指示action都有了那么就是实现了。reducer就是根据action来对state进行操作。

    const calculate = (state: ReduxState = initData, action: Action ) => {
        switch (action.type) {
            case INCREMENT:
                return {num: state.num + action.count}
            case REDUCE:
                return {num: state.num - action.count}
            default:
                return state
        }
    }
    export {calculate}
    

    通过reducer操作后返回一个新的state,比如这里根据action的type分别对state.num进行加减.

  4. store

    store就是整个项目保存数据的地方,并且只能有一个。创建store就是把所有reducer给它。

    import { createStore, combineReducers } from "redux";
    import { calculate } from "./calculate";
    
    // 全局你可以创建多个reducer 在这里统一在一起
    const rootReducers = combineReducers({calculate})
    // 全局就管理一个store
    export const store = createStore(rootReducers)
    
  5. dispatch

    store.dispatch()是组件发出action的唯一方法。

    store.dispatch(incrementAction);
    

    通过store调用incrementAction,那么就直接把store里的数据修改了。


028f64f2fdae77c9eeff48b88e883cc4.png

文件目录

*---store   // 存放redux,数据,以及action
    *---store子目录
    actions  // 存放action的文件夹
    reducers // 存放reducer的文件夹
    actionTypes.js // 存放所有的actionType
    index.js // store的入口文件

安装过程

$ npm install redux react-redux --save
$ cnpm install redux react-redux --save
$ yarn add redux react-redux 

使用步骤

  1. 先在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')
    );
    

    connect方法生成容器组件时,我们定义了一堆的逻辑和状态,而只有顶层容器能拿到store的时候才有意义,因此需要让容器组件拿到store的state对象。

    React-Redux 提供Provider组件,可以让组件树中的任意一个容器组件拿到state。

  2. 接着在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; 
    
  3. 在src/index.js中引入store,并且在Provider组件上使用

    /**之前的代码**/
    import store from './store';
    
    ReactDOM.render(
        <Provider store={store}>
            <App />
        </Provider>,
        document.getElementById('root')
    );
    
  4. 接着可以先定义数据,即定义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;
    }
    
  5. 在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上边的数据了

  6. 在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
        } 
    }
    

    mapStateToProps是一个函数。它的作用就是建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系。也就是拿一部分有用的state,映射到当前容器组件的props中,以便于通过props直接引用。

    mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。

    作为函数,mapStateToProps执行后应该返回一个对象,里面的每一个键值对就是一个映射

  7. 接着,在抛出的时候调用connect方法改造当前组件

    // connect的第一个参数为数据,即mapStateToProps方法
    // 接着在第二个括号内传入当前需要被改造的组件  
    export default connect(mapStateToProps)(App);
    

    React-Redux 提供了connect方法,用于将 UI 组件包装成容器组件。
    但是正如我们刚才提到的,顶层容器是要有状态有业务逻辑的,因此在connect方法生成顶层容器时,我们就应该把所需要的状态和业务逻辑定义好并提供给connect。
    因此,connect方法如上代码

    其中,connect方法接受两个参数:mapStateToProps和mapActionToProps(也有叫mapDispatchToProps)。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。

  8. 然后,我们在被改造的组件内就可以通过this.props.属性名获取store中的数据了,例如我在mapStateToProps方法中返回的是count数据,所以我在App组件中使用this.props.count即可

    class App extends Component {
       render() {
           return (
               <div>
                   {this.props.count}
               </div>
           );
        } 
    }
    

    获取到数据之后,接着应该是修改仓库内的数据


  1. 修改数据首先需要定义一个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';
    
  2. 接着在src/store/reducers/countReducer.js中,引入ADD_COUNT常量,并使用switch语句,或者if语句对action.type进行判断,当触发这个action的时候,让当前这个reducer的state.count加1

    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

  3. 在App.js或者是使用store的组件中,首先引入addCount方法,然后在mapStateToProps的下边,在定义一个mapActionToProps方法,接着在connect的第二个参数位置,传入这个方法即可

  4. 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';
    
  5. 而且,在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;
        }
    }
    
  6. 在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()方法,并传入一个参数即可

  7. 最后,为了遵循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
    }
    

评论