yarn add redux-saga
mysaga.js 定义saga文件
import {call, put, takeEvery} from 'redux-saga/effects'
// 模拟登陆接口
const UserService = {
login(name) {
return new Promise((resolve, reject) => {
console.log('login', name)
setTimeout(() => {
if(name === '小明') {
console.log('suc')
resolve({name: '小明'})
} else {
reject({name: '用户名或密码错误'})
}
}, 1000)
})
}
}
function* loginHandle(action) { // generator将异步操作改为同步
console.log('loginHandle', action)
try{
const res = yield call(UserService.login, action.name) //call执行UserService.login,并且将action.name当参数传递过去
console.log('res', res)
yield put({type: 'requestSuccess', res}) // put和dispatch类似,执行reducer
} catch (error) {
console.log('error', error)
yield put({type: 'requestFailure', error})
}
}
function* mySaga() {
yield takeEvery('login', loginHandle) // 类似于将函数重命名,调用login则会执行loginHandle,并且将login得参数传递过去
}
export default mySaga
store.js 存储公共状态文件
import {createStore, combineReducers, applyMiddleware} from 'redux'
import thunk from 'redux-thunk' // 此处没有用到
import createSagaMiddleware from 'redux-saga' // 引入createSagaMiddleware
import mySaga from '../mySage'
const initalLogin = {
isLogin: false, // 是否登陆
loading: false, // 登陆状态
name: '',
error: ''
}
const sagaMiddleware = createSagaMiddleware() // 创建中间件
function loginReducer(state = {...initalLogin}, action) {
console.log('loginReducer', action)
switch (action.type) {
case 'requestLogin':
return {...state, loading: true}
case 'requestSuccess':
return {...state,isLogin: true, loading: false}
case 'requestFailure':
return {...state,isLogin: false, loading: false, error: action.error.name}
default:
return state
}
}
const store = createStore(
combineReducers({user: loginReducer}),
// applyMiddleware(thunk)
applyMiddleware(sagaMiddleware) // 将中间件放入applyMiddleware
)
sagaMiddleware.run(mySaga) // 此处必须执行run()
export default store
loginPage.js 具体调用页面
import React, {Component} from 'react';
import {Redirect} from 'react-router-dom'
import {connect} from "react-redux";
class LoginPage extends Component {
constructor(props) {
super(props);
this.state = {
name: ''
}
}
changeName = (event) => {
this.setState({
name: event.target.value
})
}
render() {
const {isLogin,loading, location, loginSuccess, login, error} = this.props
console.log('loginPage', this.props)
const {name} = this.state
if(isLogin) {
const {redirect = '/'} = location.state || {}
return <Redirect to={redirect} />
}
return (
<div>
<h1>loginPage</h1>
<input type="text" value={name} onChange={this.changeName}/>
<button onClick={() => login(name)}>{loading ? '登录中': '登录'}</button>
{
error && (<p>{error}</p>) // 有错误信息则显示
}
</div>
);
}
}
const mapStateToprops = state => {
return {
isLogin: state.user.isLogin,
loading: state.user.loading,
error: state.user.error
}
}
const mapDispatchToProps = { // 方法映射到props上
// loginSuccess: () => {
// return {type: 'requestSuccess'}
// },
// loginSuccess: () => dispatch => {
// dispatch({type: 'requestLogin'})
// setTimeout(() => {
// dispatch({type: 'requestSuccess'})
// }, 2000)
// },
login : (name) => { // 这里会接收到调用login方法传得得参数
return ({type: 'login', name})
}
}
export default connect(mapStateToprops, mapDispatchToProps)(LoginPage)
以下是数据传递方式



