实战:使用 Redux-Saga 登录

新建user.php

<?php
header('Access-Control-Allow-Origin:*');  
header('Access-Control-Allow-Methods:GET,POST');  
header('Access-Control-Allow-Headers:x-requested-with,content-type');
sleep(1);
$result = new stdClass();
$result->message = "error username or password";
$result->status = "error";
if (isset($_POST["user_name"]) && isset($_POST["user_pass"])) {

    $get_userName = $_POST["user_name"];
    $get_userPass = $_POST["user_pass"];
    if($get_userName == "shenyi" && $get_userPass == "123") {

        $result->message = "login success";
        $result->status  = "success";
    }
}
header("content-type:application/json");
exit(json_encode($result));     
?>

新建 /redux/UserReduce.js

export default (state = { btnDisabled: false }, action) => {
    switch (action.type) {
        case 'UPDATE_USERFORM':
            return Object.assign({}, state, action.Form)
        case 'ACTIVE_CHANGE':
            return Object.assign({}, state, { btnDisabled: action.btnDisabled })
        default:
            return state
    }
}

新建 /redux/UserSaga.js

import { call, put, takeEvery, select} from 'redux-saga/effects'
import axios from 'axios'
import qs from 'qs'

class UserAPI {
    static userLogin (user_name, user_pass) {
        return axios.post('http://localhost:8080/user.php', qs.stringify({ user_name: user_name, user_pass: user_pass })).then((res) => res.data)
    }
}

export function* UserSaga () {
   yield takeEvery('USER_LOGIN', function* (action) {
        // 登录时,先使用 dispatch 通知 ACTIVE_CHANGE,禁止按钮
        yield put({type: 'ACTIVE_CHANGE', btnDisabled: true})
        // 获取state
        const getState = yield select()
        // ajax
        const result   = yield call(UserAPI.userLogin, getState.userName, getState.userPass)
        // 查看是否成功
        alert(result.status)
        // 异步完成,再使用 dispatch 通知 ACTIVE_CHANGE,激活按钮
        yield put({type: 'ACTIVE_CHANGE', btnDisabled: false})
    })
}

修改main.js

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore ,applyMiddleware } from 'redux'
import UserReduce from './redux/UserReduce'
import {UserSaga} from './redux/UserSaga'
import createSaga from 'redux-saga'

let saga = createSaga()
let store = createStore(UserReduce,applyMiddleware(saga))
saga.run(UserSaga)

class UserLogin extends React.Component {
    constructor (props) {
        super(props)
        this.S = this.props.Store
    }
    componentWillMount () {
        this.S.subscribe(() => {this.forceUpdate()})
    }
    textChange (e, key) {
        this.props.Store.dispatch({type: 'UPDATE_USERFORM', Form:{[key]: e.target.value }})
    }
    userSubmit () {
        this.S.dispatch({type: 'USER_LOGIN'})
    }
    render () {
        return <div>
            <h2>用户登录</h2>
            <div><span>用户名:</span><input type = 'text' onChange = { e => {this.textChange(e, 'userName')} }/></div>
            <div><span>密  码:</span><input type = 'text' onChange = { e => {this.textChange(e, 'userPass')} }/></div>
            <div><button disabled = { this.S.getState().btnDisabled } onClick = { this.userSubmit.bind(this) }> 点这里登录 </button></div>
        </div>
    }
}

ReactDOM.render(
    <UserLogin Store = { store }/>,
    document.getElementById('root')
)


知识点

1、哪怕和 saga,thunk 融合,dispatch 也是可以通知到自定义在reduce.js中的action的。那如果saga.js 和 reduce.js 重复定义如何?答案是都会调用、先调用 reduce.js 的, 再调用saga.js的。

results matching ""

    No results matching ""