Redux-Saga是什么?
redux-saga 作为 redux-thunk的代替品。它提供了生成器函数的方式来进行异步请求。提供了更为复杂的业务操作
学习曲线也比thunk高很多。但作为热门的Redux中间件。还是必须掌握一下的。
代码依然是基于 <实战:点赞>
传送门
<Redux-saga github>:https://github.com/redux-saga/redux-saga
<Redux-saga 官网>: https://redux-saga.js.org/
安装插件
$ yarn add redux-saga
修改main.js, 使 redux 集成 redux-saga,并对saga进行初始化
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, applyMiddleware } from 'redux'
import createSaga from 'redux-saga'
import NewsReduce from './redux/NewsReduce'
import { NewsSaga } from './redux/NewsSaga'
let saga = createSaga()
let store = createStore(NewsReduce, applyMiddleware(saga))
saga.run(NewsSaga)
class InfoDetail extends React.Component {
constructor (props) {
super(props)
this.S = this.props.Store
}
componentWillMount () {
this.S.subscribe(() => this.forceUpdate())
}
render () {
return <div>
<h2>新闻标题: { this.S.getState().title }</h2>
<span>当前点赞数: { this.S.getState().agreeNum }</span>
<button onClick = { () => this.S.dispatch({type: "SAGA_001", newsid: 101}) }> 点赞 </button>
<button onClick = { () => this.S.dispatch({type: "SAGA_002", newsid: 101}) }> 获取当前点赞数 </button>
</div>
}
}
ReactDOM.render(
<InfoDetail Store = {store}/>,
document.getElementById('root')
)
新建 redux/NewsSaga.js
import { call, put, takeEvery } from 'redux-saga/effects'
import axios from 'axios'
import qs from 'qs'
class NewsApi {
static setAgreeAjax (newsid) {
return axios.post('http://localhost:8080/news.php', qs.stringify({ newsid: newsid })).then(res => res.data.agree)
}
static getAgreeAjax (newsid) {
return axios.get("http://localhost:8080/news.php", { params: { newsid: newsid }} ).then(res => res.data.agree)
}
}
export function* NewsSaga () {
// SAGA_001
yield takeEvery("SAGA_001", function* (action) {
// ajax
let n = yield call(NewsApi.setAgreeAjax, action.newsid)
// dispatch
yield put({type: "SET_AGREE", agreeNum: n })
})
// SAGA_002
yield takeEvery("SAGA_002", function* (action) {
// ajax
let n = yield call(NewsApi.getAgreeAjax, action.newsid)
// dispatch
yield put({type: "GET_AGREE", agreeNum: n })
})
}
redux/NewsReduce.js 保持不变
let newsData = {
title : '测试新闻标题',
agreeNum : 0
}
export default (state = newsData, action) => {
switch (action.type) {
case 'GET_AGREE':
return Object.assign({}, state, { agreeNum : action.agreeNum })
case 'SET_AGREE':
return Object.assign({}, state, { agreeNum : action.agreeNum })
default:
return state
}
}
知识点
1、saga.run(NewsSaga) 中必须绑定一个生成器函数
2、takeEvery第一个参数是一个自定义名称,用于被外部dispatch指定。第二个参数必须是一个生成器函数。