最近在捣鼓react,我是由vue转过来的,所以在学react的时候和vue做了相应的功课和比较。结论是,没有哪个好,只有那个更适合当前的项目(完全是废话)!开始切入主题。
其实在网上一搜,一大把大把的资料,我开始也是在网上搜啊搜啊,发现里面说的还不如去看官方文档。react saga 中文文档
里面讲的很详细,我这里就此略过。大家可以先去看看文档,在回过来看,或者看了我写的这个,再去看文档。我这个可完全是自己慢慢想慢慢做出来。
我们要想象saga作为中间件,它是处于什么位置中,它所起的作用是什么?想想saga是怎么能够一步步监控,在整个项目中的流程是什么样的?
对于这是,我们是这样理解的
第一步,我们定义action ,在使用thunk的时候,我们是在action里面直接调用的异步ajax,fetch,axios 或者jq 的ajax。(thunk的缺点自行百度); 但是在saga里面,是直接返回的一个action,这个action将会被saga监控到,
login==>index.js
import React, { Component } from "react";
import { connect } from "react-redux";
import md5 from "md5";
import { Form, Icon, Input, Button } from "antd";
import {
sendLoginRequest,
// getTokenAction
} from "../../store/actions/loginAction";
const FormItem = Form.Item;
/**
*
*
* @class Login
* @extends {Component}
*/
class Login extends Component {
constructor(props) {
super(props);
this.state = {
mobile: "",
password: ""
};
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
this.props.form.setFieldsValue({
mobile:''
});
}
handleSubmit(e) {
e.preventDefault();
const {dispatch}=this.props;
this.props.form.validateFields((err, values) => {
if (!err) {
// console.log("Received values of form: ", values);
let params = Object.assign({}, values, {
password: md5(values.password),
loginType: 0
});
console.log(params)
dispatch(sendLoginRequest(params))
// this.props.userLoginAction(params);
}
});
}
render() {
const { getFieldDecorator } = this.props.form;
return (
<div className="login-wapper">
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator("mobile", {
rules: [
{ required: true, message: "Please input your username!" }
]
})(
<Input
prefix={
<Icon type="user" style={{ color: "rgba(0,0,0,.25)" }} />
}
placeholder="Username"
/>
)}
</FormItem>
<FormItem>
{getFieldDecorator("password", {
rules: [
{ required: true, message: "Please input your Password!" }
]
})(
<Input
prefix={
<Icon type="lock" style={{ color: "rgba(0,0,0,.25)" }} />
}
type="password"
placeholder="Password"
/>
)}
</FormItem>
<FormItem>
<Button
type="primary"
htmlType="submit"
block
className="login-form-button"
>
Log in
</Button>
</FormItem>
</Form>
</div>
);
}
}
const LoginForm = Form.create()(Login);
export default connect(null)(LoginForm);
action.js
import { USER_LOGIN, GET_TOKEN,USER_LOGIN_REQUEST } from "../mutations/type";
export const sendLoginRequest=(params)=>({type:USER_LOGIN_REQUEST,params})
saga =>index.js
import { call, spawn } from "redux-saga/effects";
//获取当前目录下的所有文件
const context = require.context("./", true, /\.js$/);
// 分解获取的文件值
const keys = context.keys().filter(item => item !== "./index.js");
let sagas = [];
for (let i = 0, len = keys.length; i < len; i++) {
const exp = context(keys[i]);
for (let fn in exp) {
sagas.push(exp[fn]);
}
}
export default function* rootSaga() {
yield sagas.map(saga =>
spawn(function*() {
while (true) {
try {
// console.log(saga,'-----')
yield call(saga);
break;
} catch (e) {
console.log(e);
}
}
})
);
}
saga=>getToken.js
import { call, take,put } from "redux-saga/effects";
import { setCookie, getCookie } from "../assets/utils";
import service from "../service";
export function* getToken() {
if(!getCookie('token')){
yield call(getTokenFetch)
}
}
function* getTokenFetch() {
const result= yield call(service.artGetTokenService,{ctype:0});
setCookie("token", result.data);
}
export function* getLoginRequest() {
try {
const action = yield take("USER_LOGIN_REQUEST");
let res=yield call(service.artUserLoginService,action.params)
console.log(res);
} catch (error) {
console.log(error);
}
}
我们就拿一个简单的项目为例子:
目录结构:
reduce 没有变化,变化的地方就是action 就是一个指令作用