2016-01-12 65 views
0

我一直在尋找一種優雅(正確)的方式來處理登錄Redux應用程序。目前,該用戶被定向到一個登錄組件/容器,他在那裏看到一個帶有用戶名和密碼的表單。然後,當他點擊提交時,我調用一個異步登錄函數,當承諾履行時,我派遣一個loginSuccess和一個replacePath調用。以下是一些僞代碼:Redux登錄

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

這有效,但我不確定這是最佳實踐。任何人有更好的實現?

+0

這是否在您的實際React組件中?我認爲使用'redux-thunk'時推薦的策略是在異步操作創建器中實現該邏輯,以避免將應用程序邏輯綁定到用戶界面。 – rossipedia

+0

是的,目前我在那裏,因爲我不確定我應該在路由器上使用替換路徑和動作創建者的東西。這是一個更可取的策略,我也允許從動作創建者訪問路由器嗎? – kjonsson

回答

1

它通常被認爲是不好的做法,調用組件內的調度,除非它的頂級容器連接到商店。

我建議遵循Dan Abramov在文檔中給出的例子,最值得注意的是async Reddit post fetching example。看看他如何用posts.isFetching來處理請求的臨時過程。

因爲我知道的StackOverflow不喜歡的鏈接,這裏有一個簡單的例子(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()。驗證發送requestAuth(),它更新狀態以向用戶顯示請求正在處理中(加載微調器顯示或其他內容)。一旦你的AJAX對後端的調用返回了認證結果,你可以調用authSuccess()或authFail()來更新狀態並通知用戶他們的請求是否成功。

+0

我同意這樣更優雅。但是當登錄成功時,我仍然需要知道在哪裏以及如何進行重定向。我想派發replacePath,它是一個可以分派來改變路由的react-router或者redux-simple-router功能。 – kjonsson

+0

在我的示例中籤出'authenticate()'動作的結尾。我寫了一條評論,告訴你可以在哪裏調用'dispatch(pushPath('/'))'。您可以將該調用放入條件成功塊中。 – bean

+0

謝謝。今晚我會試試這個。 – kjonsson