Redux 登录

Redux logging in

我一直在寻找一种优雅(且正确)的方式来处理 Redux 应用程序的登录。当前,用户被定向到登录 component/container,他在其中看到带有用户名和密码的表单。然后,当他点击提交时,我会调用一个异步登录函数,当承诺得到满足时,我会发送一个 loginSuccess 和一个 replacePath 调用。以下是一些伪代码:

submit(e) {
   login(username, password)
      .then(function (user) {
         dispatch(loginSuccess(user));
         dispatch(replacePath('/');
      });
}

这可行,但我不确定这是最佳做法。谁有更好的实现方式?

在组件内调用调度通常被认为是不好的做法,除非它是一个连接到商店的 top-level 容器。

我建议遵循 Dan Abramov 在文档中提供的示例,尤其是 async Reddit post fetching example。看看他是如何处理posts.isFetching.

请求的中间过程的

因为我知道 Whosebug 不喜欢链接,这里有一个简化的例子(在 ES6 中):


这些是操作:

// Actions

import fetch from 'isomorphic-fetch';
import * as types from '../constants/actionTypes.js';
var requestAuth = function() {
    return {
        type: type.REQUEST_AUTH
    }
};

var authSuccess = function(response) {
    return {
        type: type.AUTH_SUCCESS,
        response: response
    }
};

var authFail = function(response) {
    return {
        type: type.AUTH_FAIL,
        response: response
    }
};

var authenticate = function(username, password) {
    var fetchOptions = {
        method: 'post',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({username: username, password: password})
    };
    var uri = '/api/path/to/your/login/backend';
    return dispatch => {
        dispatch(requestAuth);
        return fetch(uri, fetchOptions)
            .then(response => {
                if (resopnse.status === 200) {
                    dispatch(authSuccess(response));
                    // Do any other login success work here
                    // like redirecting the user
                } else {
                    dispatch(authFail(response));
                }
            }
    }
};

下一个减速器:

// Reducer
import { combineReducers } from 'redux';
import { REQUEST_AUTH, AUTH_SUCCESS, AUTH_FAIL } from '../actions/login';

function login(state = {
    isAuthenticating: false,
    isLoggedIn: false,
    authenticationToken: '',
    authError: null
    .....,   // whatever other state vars you need
    .....
    }, action) {
        switch(action.type) {
            case REQUEST_AUTH:
                return Object.assign({}, state, {
                    isAuthenticating: true
                });
                break;
            case AUTH_SUCCESS:
                return Object.assign({}, state, {
                    isAuthenticating: false,
                    isLoggedIn: true,
                    authenticationToken: action.response.token
                });
                break;
            case AUTH_FAIL:
                return Object.assign({}, state, {
                    isAuthenticating: false,
                    authError: action.response.error
                });
            break;
           default:
                return state;

    }
}

最后是组件方法

// Component Method
// authenticate() should be wrapped in bindActionCreators()
// and passed down as a prop
function handleSubmit(username, password) {
    if (isValid(username) && isValid(password) {
        authenticate(username, password);
    }
}

tl;dr 您的用户输入的凭据应该是状态的一部分(此处未显示)。组件中的 onClick 调用 handleSubmit(),它会调度 authenticate()。 Authenticate 调度 requestAuth() 更新状态以向您的用户显示请求正在处理(显示加载微调器或其他内容)。一旦您 AJAX 调用带有身份验证结果的后端 returns ,您将发送 authSuccess() 或 authFail() 来更新状态并通知用户他们的请求是否成功。