我會給在第二個工作流(登錄)一杆。
在進入代碼之前,值得注意的是redux-loop
比異步控制流程簡單很多,並且提供了小於redux-saga
。但本着Elm
的精神,重點在於數據流 - 通常通過數據類型來實現這一點並不令人意外。因此,從靜態類型語言的角度思考是有幫助的。在Haskell
或Elm
,這可能有利於模型的數據類型,其本身編碼狀態機的問題:
data LoginStatus data err =
LoggedOut |
, LoggedIn data |
, LoginError err |
, Pending
凡data
和err
是類型變量代表登錄的數據類型(標記)和登錄錯誤。 JavaScript是動態輸入的,沒有表達相同想法的好處 - 但是有很多動態技巧可以用來模擬像LoginStatus
這樣的標記聯合類型。如果沒有進一步的前,這裏是代碼:
import {match} from "single-key";
export default function reducer(state, action) {
return match(state, {
LoggedOut :() => loggedOutReducer(state, action),
LoggedIn :() => loggedInReducer(state, action),
Pending :() => pendingReducer(state, action),
LoginError :() => loginErrorReducer(state, action)
});
}
在這裏,我將使用一個簡單的和鮮爲人知的圖書館singe-key實現非常基本的運行時間聯合類型。一個「單鍵」對象,就像它的名字所暗示的那樣,是一個只有一個鍵和一個值的對象,比如{ a: 1 }
(「a」是關鍵,1是值)。我們將用單鍵對象來模擬狀態 - 不同的鍵代表LoginStatus
的不同變體。幾個例子指出:
{
LoggedOut : true
}
{
LoggedIn : {
token : 1235,
user : { firstName: "John" }
}
}
{
Pending : true
}
隨着該清理,這裏是在主減速器使用的子減速器:
// state :: { LoggedIn: {/* some data * } }
function loggedInReducer(state, action) {
if (action.type === LOGOUT) {
return {
LoggedOut : true
};
}
return state;
}
// state :: { Pending : true }
function pendingReducer(state, action) {
if (action.type === LOGIN_SUCCESS) {
return {
LoggedIn : {
token : action.payload.token,
user : action.payload.user
}
};
}
if (action.type === LOGIN_ERROR) {
return {
LoginError : action.payload;
};
}
if (action.type === LOGOUT) {
return {
LoggedOut : true
};
}
return state;
}
// state :: { LoggedOut : true }
function loggedOutReducer(state, action) {
if (action.type === LOGIN) {
return loop({ Pending: true }, Effects.promise(loginRequest));
}
return state;
}
// state :: { LoginError : error }
function loginErrorReducer(state, action) {
if (action.type === LOGIN) {
return loop({ Pending: true }, Effects.promise(loginRequest));
}
return { LoggedOut : true };
}
這些就像在有限狀態機轉變,除了有時與數據附屬於該州。每個單獨的reducer都相當簡單,並且處理很少的動作類型。只有兩個減速返回效果:
return loop({ Pending: true }, Effects.promise(loginRequest));
這種轉變從LoggedOut
/LoginError
狀態,以Pending
並指定一些副作用 - 這將由redux-loop
安排。你甚至可以將這兩個變體合併爲一個:{ LoggedOut : error | null }
,但是我覺得從長遠來看,單獨的LoginError
狀態是有益的。
對於某些數據類型的概念,這個問題比第一次出現時更容易推理;你可以用減速機做同樣的事情,結構大致相同,只用redux-thunk
。
我很欣賞這種迴應,但......這種方法的問題在於它混合了責任。異步工作流程+「正常」狀態。這導致複雜的減速器。在真正的項目中,這意味着您只是更容易創建脆弱的代碼。此外,您還沒有解決如何實際完成上述工作流程。 –
感謝您的反饋。這是合理的批評。對於最後一點,我相信我主要解決了它的工作原理。那麼,因爲我今天有一些空閒時間,所以在這裏解釋了使用減速器佈局的一個實例。它有一個'redux-loop'和'redux-sage'實現,幾乎完全相同的reducer:[https://github.com/yiransheng/redux-login-examples](https://github.com/yiransheng/redux -login-examples) –
什麼是好的是你明確枚舉類型的想法。不幸的是,正如他們在美國所說的那樣,「你正在擊敗一匹死馬。」另外,對於關注點的混合,您沒有專門處理異步性的API。因此,在現實世界的項目中,代碼變得非常非常複雜(和重複)。例如,您不處理「取消」情況。其次,FRP /傳奇在測試中勝出。你不需要嘲笑。 –