Redux-thunk和Redux-saga的入门级使用

Redux-thunk的使用

实现思路

在action中设置一个为函数的action,因为thunk中间件可以执行action函数。

本示例的表达的意思:

  • 页面需要获取到接口中的data数据,调用getListDataAction函数。
  • getListDataAction函数返回的参数不是一个对象,而是一个函数。
  • 这个action派发后,thunk中间件识别后,会执行该函数,在异步获取到数据后,会再派发type为GET_LIST_DATA的action。
  • store会再次收到一个新的action,在这个action中,store会去匹配reducer中的内容,执行相应的操作后,返回一个新的state。
  • 页面订阅了state的变化,通过setState改变了state,从而将数据存储到state中,页面也会自动刷新。

安装redux-thunk

npm install redux-thunk
// 或者
yarn add redux-thunk

在store文件中使用

github上的redux-thunk地址

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reduer from "./reduer";

const composeEnhancers =
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
        window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

const enhancer = composeEnhancers(
    applyMiddleware(thunk)
);

const store = createStore(reduer, enhancer);

export default store;

在action文件中定义

import axios from "axios";
import { ADD_VALUE, CHANG_VALUE, DEL_VALUE, GET_LIST_DATA, GET_LIST } from "./actiontypes";
export const getChangeAction = (e) => {
    return {
        type: CHANG_VALUE,
        value: e.target.value
    };
}

export const getAddAction = () => {
    return {
        type: ADD_VALUE
    };
}

export const getDelAction = (index) => {
    return {
        type: DEL_VALUE,
        index
    };
}
export const getList = () => {
    return {
        type: GET_LIST
    }
}

export const getListData = (data) => {
    return {
        type: GET_LIST_DATA,
        data
    }
}

export const getListDataAction = () => {
// 默认store只能识别对象的action,但是使用了thunk,可以通过传入一个函数,在thunk中间件中会执行
    return (dispatch) => {
        axios.get("api/todolist").then(res => {
            const action = getListData(res.data);
            dispatch(action);
        }).catch((e) => {
            console.log("获取数据失败了", e)
        })
    }
}

在页面组件中使用

  componentDidMount() {
    const action = getListDataAction();
    store.dispatch(action)
  }

Redux-saga的使用

实现源码git地址,分支是redux-saga

实现的思路

首先需要在store中创建saga中间件,该中间件用于监控当前页面中派发的action,根据action中的type参数进行筛选,匹配成功的则执行对应的函数。
设置好了saga之后,页面中根据不同的情况,派发不同的action,当store获取到action之后,saga中间件就会执行,在对应的函数中执行完成后,可以再派发action,用于执行下一步操作。

本示例的意思就是:

  • 页面想要获取到接口中的list数据,所以派发type为GET_LIST 的action。
  • 当store要执行派发的action的时候,根据saga中间件中的内容,如果有监控GET_LIST的函数,那么就要执行函数getListData。
  • 在函数getListData中,发送了axios请求,获取到数据了,那么我需要将获取到的数据存到state中,所以,请求成功后,我需要再派发type为GET_LIST_DATA 的action。
  • store会再次收到一个新的action,在这个action中,store会去匹配reducer中的内容,执行相应的操作后,返回一个新的state。
  • 页面订阅了state的变化,通过setState改变了state,从而将数据存储到state中,页面也会自动刷新。

安装 redux-saga

yarn add redux-saga
// 或者
npm install redux-saga

在store文件中使用

github上的redux-saga地址

import { createStore, applyMiddleware, compose } from 'redux';
// 
import createSagaMiddleware from 'redux-saga'
import reduer from "./reduer";
import mySaga from './sagas'

// 创建saga中间件
const sagaMiddleware = createSagaMiddleware();

// 此处内容是为了实现react-devtools的调试,配置内容参考:https://github.com/zalmoxisus/redux-devtools-extension
const composeEnhancers =
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
        window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const enhancer = composeEnhancers(
    applyMiddleware(sagaMiddleware)
);

const store = createStore(reduer, enhancer);

// 执行中间件
sagaMiddleware.run(mySaga)
export default store;

创建sagas文件

import { put, takeEvery } from "redux-saga/effects";
import { GET_LIST } from "./actiontypes";
import { getListDataAction } from "./renderStore"
import axios from "axios";

// 获取数据的函数
function* getListData() {
  try {
    // 使用异步的方式,拿到请求的结果
    const res = yield axios.get("api/todolist");
    // 获取到新的action
    const action = getListDataAction(res.data);
    // 派发新的action
    yield put (action)
  } catch (error) {
    console.log("请求todolist数据失败了", error);
  }
}

// 监控派发内容是 GET_LIST,都要执行一次 getListData函数
function* mySaga() {
  yield takeEvery(GET_LIST, getListData);
}
export default mySaga;

在页面组件中使用

// 在生命周期函数中执行
componentDidMount() {
    const action = getList();
    store.dispatch(action)
}

Redux公共部分

actiontypes.js文件内容

export const CHANG_VALUE = "change_value"; 
export const ADD_VALUE = "add_value";
export const DEL_VALUE = "del_value";
export const GET_LIST_DATA = "get_list_data";
export const GET_LIST = "get_list";

rederStore.js中的内容

import { ADD_VALUE, CHANG_VALUE, DEL_VALUE, GET_LIST_DATA, GET_LIST } from "./actiontypes";
export const getChangeAction = e => {
    return {
        type: CHANG_VALUE,
        value: e.target.value
    };
}

export const getAddAction = () => {
    return {
        type: ADD_VALUE
    };
}

export const getDelAction = index => {
    return {
        type: DEL_VALUE,
        index
    };
}
export const getList = () => {
    return {
        type: GET_LIST
    }
}
export const getListDataAction = data => {
    return {
        type: GET_LIST_DATA,
        data
    }
}

reducer.js内容

import { CHANG_VALUE, ADD_VALUE, DEL_VALUE, GET_LIST_DATA } from "./actiontypes";

const defaultState = {
    inputValue: "",
    list: []
};

// eslint-disable-next-line import/no-anonymous-default-export
export default ((state = defaultState, action: any) => {
    if (action.type === CHANG_VALUE) {
        const newState = JSON.parse(JSON.stringify(state));
        newState.inputValue = action.value;
        return newState
    }
    if (action.type === ADD_VALUE) {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.push(state.inputValue);
        newState.inputValue = "";
        return newState
    }
    if (action.type === DEL_VALUE) {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index, 1);
        return newState
    }
    if(action.type === GET_LIST_DATA) {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list = action.data;
        return newState
    }
    return state
});
上一篇:收录的一篇很详细很全的OGG配置文档


下一篇:poj2385 Apple Catching(dp状态转移方程推导)