Development Documentation
- https://redux-saga.js.org/
- https://redux-saga-in-chinese.js.org/
- https://redux-actions.js.org/
Source
Code has been uploaded to github welcomed star or fork
redux-saga
I. INTRODUCTION
Before processing the asynchronous redux-thunk + redux-actions + redux-promise, but with the advent of the Generator ES6, it was found easier to handle asynchronous be used Generator. And redux-saga is treated with asynchronous Generator.
redux-saga document does not say that they are asynchronous processing tool, but that used to deal with marginal effects (side effects), the marginal effect here you can understand the operation of the external program, such as the back-end requests, such as file operations.
redux-saga is also a redux middleware, its position is controlled by a centralized Action, functions as a controller similar to the effect of MVC.
While its syntax makes complex asynchronous operation does not appear then as many cases as promise, easier to carry out all kinds of tests.
Second, the installation
npm install --save redux-saga
Three, saga common helper
put、call、takeEvery、takeLatest
1、put和call
put equivalent to the role of dispatch redux, while the call is equivalent to calling the function
export function* delayChangeBtnText() {
yield delay(1000);
yield put(changeBtnText('123'));
yield call(consoleMsg, '完成改变');
}
2、takeEvery
It provides a similar redux-thunk behavior
import { takeEvery } from 'redux-saga'
function* watchFetchData() {
yield* takeEvery('FETCH_REQUESTED', fetchData)
}
3, takeLatest
takeEvery fetchData allows multiple instances started simultaneously. At a given moment, although there are one or more fetchData not over before we can start a new fetchData task,
if we want to get the latest response to the request (for example, always shows the latest version of the data). We can use takeLatest Helper
import { takeLatest } from 'redux-saga'
function* watchFetchData() {
yield* takeLatest('FETCH_REQUESTED', fetchData)
}
Fourth, the use
1, modified store / index.js
import { createStore, applyMiddleware } from 'redux';
// import thunk from 'redux-thunk';
import createSagaMiddleware from 'redux-saga';
import {watchAppSearch} from './sagas';
import rootReducer from './reducers';
/**
* saga用法
* 1.创建一个 Saga middleware
* 2.使用 applyMiddleware 将 middleware 连接至 Store
* 3.使用 sagaMiddleware.run(helloSaga) 运行 Saga
*/
const sagaMiddleware = createSagaMiddleware();
// 创建store的时候,第二个参数是中间件,redux-thunk提供了一个thunk中间件,用于处理异步的action
let store = createStore(
rootReducer,
applyMiddleware(sagaMiddleware)
);
// 运行并监控各个action
sagaMiddleware.run(watchAppSearch);
export default store
2, create a store / sagas.js
import { put, call, takeEvery,takeLatest } from 'redux-saga/effects';
import { actionCreators } from './action'
import $api from '../api/index.js';
/**
* 处理编辑效应的函数
*/
export function* appSearch(action) {
// 在saga中这里通过action.payload获取到前台传过来的keyword内容
const p = function(){
return $api.lookUp({
keyword:action.payload
})
.then(res => res.results)
.then(res =>{
return res
})
}
const res = yield call(p); // 执行p函数,返回值赋值给res
yield put(actionCreators.saveSearchList(res));// 通过put触发dispatch ,将返回数据传过去
}
/**
* 监控Action的函数
*/
// takeLatest 和 takeEvery 不同,在任何时刻 takeLatest 只允许一个 fetchData 任务在执行。
// 并且这个任务是最后被启动的那个。 如果已经有一个任务在执行的时候启动另一个 fetchData ,那之前的这个任务会被自动取消。
export function* watchAppSearch() {
yield takeEvery(actionCreators.appSearch, appSearch);
}
3, start multiple Sagas monitor action action
// 同时启动多个Sagas 监听action动作
export default function* rootSaga() {
yield all([
takeLatest(actionCreators.appSearch, appSearch),
takeLatest(actionCreators.getRecommendList, getRecommendList)
])
}
/**
* app搜索获取结果列表
*/
export function* appSearch(action) {
// 在saga中这里通过action.payload获取到前台传过来的keyword内容
const p = function(){
return $api.lookUp({
keyword:action.payload
})
.then(res => res.results)
.then(res =>{
return res
})
}
const res = yield call(p); // 执行p函数,返回值赋值给res
yield put(actionCreators.saveSearchList(res));// 通过put触发dispatch ,将返回数据传过去
}
/**
* 请求获取推荐列表
* @param {*} action
*/
export function* getRecommendList(action) {
const p = function(){
return $api.recommendData({})
.then(res => res.feed)
.then(res =>{
return res
})
}
const res = yield call(p); // 执行p函数,返回值赋值给res
yield put(actionCreators.getRecommendListSucceeded(res.entry));
}
redux-actions
redux redux-actions to simplify the code repetition, this work focuses on simplifying part construction and action processing aspects reducers.
First, install
npm install --save redux-actions
Second, the use
-----action.js
import * as types from './action-types'
import { createActions } from 'redux-actions';
/**
* 使用redux-actions之前
*/
// export const saveSearchList = (searchList) => {
// console.log('searchList',searchList)
// return {
// type: types.SAVE_SERACH_LIST,
// searchList
// }
// }
// export const removeSearchList = () => {
// return {
// type: types.REMOVE_SERACH_LIST
// }
// }
/**
* 使用redux-actions之后
*/
// 使用createAction创建单个动作
// export const saveSearchList = createAction(types.SAVE_SERACH_LIST,searchList=>searchList);
// export const removeSearchList = createAction(types.REMOVE_SERACH_LIST);
// 使用createActions创建多个动作
export const actionCreators = createActions({
[types.SAVE_SEARCH_LIST]:searchList=>searchList,
[types.REMOVE_SEARCH_LIST]:()=>null
});
-----reducer.js
import * as types from './action-types'
import { handleActions } from 'redux-actions';
let defaultState = {
searchList: []//搜索结果列表
}
/**
* 使用redux-actions之前
*/
// 修改state
// export default(state = defaultState, action={})=>{
// switch (action.type) {
// case types.SAVE_SERACH_LIST:
// return {
// ...state,
// searchList: action.searchList
// }
// case types.REMOVE_SERACH_LIST:
// return{
// ...state,
// searchList:[]
// }
// default:
// return state
// }
// }
/**
* 使用redux-actions之后
*/
// handleAction单个action处理
// const reducer = handleAction(types.SAVE_SERACH_LIST,(state, action)=>{
// return {
// ...state,
// searchList: action.searchList
// }
// },defaultState);
// 使用handleActions处理多个actions ,这里需要注意的是 通过action.payload获取传过来的数据
const reducerCreators = handleActions({
[types.SAVE_SEARCH_LIST]:(state, action)=>{
return {
...state,
searchList: action.payload
}
},
[types.REMOVE_SEARCH_LIST]:(state, action)=>{
return{
...state,st
searchList:[]
}
}
},defaultState);
export default reducerCreators;
---index.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { actionCreators } from '../../store/action'
/**
* 使用redux-action之前
*/
// const mapDispatchToProps = (dispatch) => ({
// 分发由action creators创建的actions
// saveSearchList: searchList => dispatch(saveSearchList(searchList)),
// removeSearchList: () => dispatch(removeSearchList())
// })
/**
* 使用redux-action之后
*/
// createActions会返回一个对象,对象针对每个action类型都有一个值为action工厂的属性,属性名为action类型的值去掉下划线后的驼峰命名
const mapDispatchToProps = {
saveSearchList:actionCreators.saveSearchList,
removeSearchList:actionCreators.removeSearchList
}
// 通过connect生成容器组件
export default connect(mapStateToProps,mapDispatchToProps)(SearchResult);
Source
Code has been uploaded to github welcomed star or fork
Reference Reading
- https://juejin.im/post/5b41641ef265da0f8202126d
- https://www.jianshu.com/p/d2615a7d725e
- https://segmentfault.com/a/1190000017064759?utm_source=tag-newest