初识react(六) redux-thunk实现简单异步计数Demo(补充)

1,249 阅读3分钟

回顾

三个react中常用的中间件 redux-thunk、redux-promise、redux-logger,跟着demo来看下如何使用吧

先把目录结构搭好

下面我们讲解下每个文件的作用,然后在一个一个实现

  • actions->counter.js存放计数器的动作
  • reducers->index.js是主入口文件,因为可能有好多个reducer。
  • reducers->counter.js存放计数器的reducer
  • store->index.js 是整个store对外暴露的入口文件

概念篇 初始react(二) 读完这篇文章,相信对redux中的概念已经熟悉了。

一、编写store部分

1、编写reducers/counter.js文件

  • 是一个计数器的reducer,reducers目录下可能有很多个reducer,我们先写一个
let initState = {  //声明一个初始的状态
    number:0
};
function counter(state = initState, action) {   //接收state和action两个参数,并给state赋予初始值
    switch (action.type) {  //判断动作类型
        case Types.INCREMENT: //action类似这种结构{type:'INCREMENT',count:5}
            return {number:state.number+action.count};
        case Types.DECREMENT:
            return {number:state.number-action.count};
    }
    return state    
}
export default counter

2、编写reducers/index.js文件

  • 由于我们只有一个计数器的reducer,项目中肯定会有多个reducer,在这个文件中进行合并。
import counter from "./counter"; 
import {combineReducers} from "redux";
export default combineReducers({counter});   //可能会有多个reducers,目前只有一个counter的reducer

3、 编写actions/counters.js

  • 把派发的动作抽离出来,用于来组件中调用,redux-thunk中间件允许我们返回函数,并把dispatch、getState暴露出来
import axios from "axios";
let actions = {
    add(num){
        /*redux-thunk允许你actionCreator返回的是一个函数,
        * 如果是函数,会让函数执行 并且把dispatch的权利转交给你,
        * 你可以在想要的时机派发事件
         */
        return async (dispatch,getState)=>{
           let result = await axios.get('https://www.easy-mock.com/mock/5b7bdbf95b040679770764fb/example/mock');
           let {num} = result.data;
            dispatch({type:'increment',count:num})
        }
    },
    minus(num){
        return {type:'decrement',count:num}
    }
};
export default actions

5、编写store/index.js,仓库的主文件

  • 这个文件主要用于导出store,提供给组件使用
import {createStore,applyMiddleware} from 'redux';
import reducer from "./reducers"
import reduxThunk from "redux-thunk";
import reduxPromise from "redux-promise";
import reduxLogger from "redux-logger";
//使用中间件 reduxThunk、reduxPromise、reduxLogger
let store = createStore(reducer,applyMiddleware(reduxThunk,reduxPromise,reduxLogger));
export default store;

截止到目前为止,store文件已经全部写完。下面我们开始写组件部分,让仓库中数据给组件使用

二、组件调用部分

1、编写react的主入口文件,即 src/index.js

  • 使用react-redux库,来实现store和组件之间的通信
  • react-redux提供了2个核心API, Provider 提供 connect 链接
  • Provider是一个组件,在react入口文件中用于提供store。
  • connect含义是,在react组件内部连接store,进而实现组件与redux之间通信
import React from 'react';
import ReactDOM from 'react-dom';
import Counter from "./components/Counter";
import store from "./store";
//react-redux暴露两个方法,一个Provider,一个Connect。
import {Provider} from "react-redux";
ReactDOM.render(
    <Provider store = {store}>
        <React.Fragment>
            <Counter />
        </React.Fragment>
    </Provider>, document.getElementById('root'));

2、编写Counter组件

  • 组件中用到connect方法,实现组件与redux之间通信,connect方法接受2参数。connect(mapStateToProps,actions)(Counter)
  • 把store/actions.js导出的对象绑定到组件的属性中,组件内部可以通过this.props拿到对应的actions
import React from "react";
//生成action的对象的方法叫actionCreator
import actions from "../store/actions/counter";
import {connect} from "react-redux";
class Counter extends React.Component {
    render() {
        console.log('props',this.props);
        return (
            <div>
                <button onClick={()=>{
                    this.props.add()
                }}>+</button>
                <div>{this.props.number}</div>
                <button onClick={()=>{
                    this.props.minus(1)
                }}>-</button>
            </div>
            )
    }
}
let mapStateToProps = (state)=>{ //state代表的store.getState()
    return {...state.counter}
};

export default connect(mapStateToProps,actions)(Counter)  

到此为止,我们基本实现一个计数器功能,先来测试下。

点击增加 异步记数功能

功能基本实现,可能对整个流程并不清楚怎么实现的,下面来梳理下整个工作流程

react-redux整个流程分析

  • 当点击按钮触发 this.props.add(),异步获取数据,然后派发动作,看actions/counter.js文件
  • 派发动作后被reducer处理,然后返回新的状态
  • 页面刷新

最后来张图结尾