react-thunk
redux-thunk:
处理函数型action的中间件
asyAdd = () => { // 模拟下异步数据请求 store.dispatch((dispatch, getState) => { setTimeout(() => { console.log("getState", getState()); dispatch({type: "ADD"}); }, 1000); }); };
// store/index.js import {loginReducer} from "./loginReducer"; import {createStore, combineReducers, applyMiddleware} from "redux"; import thunk from "redux-thunk"; import login from "../action/user"; const store = createStore( combineReducers({user: loginReducer}), applyMiddleware(thunk) ); export default store;
// store/loginReducer.js const userInit = { isLogin: false, userInfo: {id: null, name: "", count: 0}, loading: false, err: {msg: ""} }; // 定义用户基本信息修改规则 export const loginReducer = (state = {...userInit}, {type, payload}) => { switch (type) { case "REQUEST": return {...state, loading: true}; case "LOGIN_SUCCESS": return {...state, isLogin: true, loading: false, userInfo: {...payload}}; case "LOGIN_FAILURE": return {...state, ...userInit, ...payload}; case "LOGOUT_SUCCESS": return {...state, isLogin: false, loading: false}; default: return state; } };
// action/user export const login = userInfo => dispatch => { dispatch({type: "REQUEST"}); LoginService.login(userInfo).then( res => { // dispatch({type: "LOGIN_SUCCESS", payload: res}); // 异步请求嵌套 getMoreUserInfo( dispatch, res); }, err => { dispatch({type: "LOGIN_FAILURE", payload: err}); } ); };
// service/index.js 模拟登录接口 const LoginService = { login(userInfo) { return new Promise((resolve, reject) => { setTimeout(() => { if (userInfo.name === "dd") { resolve({ id: 123, name: "omg原来是dd" }); } else { reject({ err: { msg: "用户名或密码错误" } }); } }, 1000); }); }, // 获取更多信息 getMoreUserInfo(userInfo) { return new Promise((resolve, reject) => { setTimeout(() => { if (userInfo.id === 123) { resolve({ ...userInfo, count: "100" }); } else { reject({ msg: "获取详细信息错误" }); } }, 1000); }); }, }; export default LoginService;
// LoginPage.js import React, {Component} from "react"; import {Redirect} from "react-router-dom"; import {connect} from "react-redux"; import {login} from "../action/user"; @connect( ({user}) => ({isLogin: user.isLogin, loading: user.loading, err: user.err}), { login: userInfo => ({type: "LOGIN_SUCCESS", payload: userInfo}) } ) class LoginPage extends Component { constructor(props) { super(props); this.state = {name: ""}; } nameChange = e => { this.setState({name: e.target.value}); }; render() { const {isLogin, location, dispatch, login, loading, err} = this.props; // 登录 if (isLogin) { const {from = "/"} = location.state || {}; return <Redirect to={from} />; } const {name} = this.state; return ( <div> <h3>LoginPage</h3> <input value={name} onChange={this.nameChange} /> <button onClick={() => login({name})}> {loading ? "loading..." : "login"} </button> <p className="red">{err.msg}</p> </div> ); } } export default LoginPage;
宝剑锋从磨砺出,梅花香自苦寒来。