2017-03-19 40 views
0

我是新来Redux的观测:https://github.com/redux-observable/redux-observableRedux Observables:对于相同的动作,但不同的过滤器,分开史诗?

我有一个简单的例子,我想这样做基于用户的signedIn状态2个不同的东西。

  1. 如果登录,添加RSVP
  2. 如果没有登录,模态

显示标志我在app/redux/epics/addRSVP.js文件中有这样的:

import 'rxjs'; 
import * as scheduleActions from '../ducks/schedule'; 

export default function searchUsers(action$, store) { 
    return action$.ofType(scheduleActions.ADD_RSVP) 
    .filter(() => store.getState().user.signedIn) 
    .map(action => scheduleActions.rsvpAdded(action.payload)); 
}; 

我的问题是,应该我正在为注销的用例创建另一个app/redux/epics/preventRSVPIfNotSignedIn.js史诗?是这样的:

import 'rxjs'; 
import * as authenticationActions from '../ducks/authentication'; 

export default function searchUsers(action$, store) { 
    return action$.ofType(scheduleActions.ADD_RSVP) 
    .filter(() => !store.getState().user.signedIn) 
    .map(action => authenticationActions.show()); 
}; 

或者有没有办法我可以把两者都放在同一个文件中?我觉得如果它是前者,它最终会成为很多史诗。知道一般惯例是什么会很棒。

回答

2

如果您不确定,请始终创建单独的史诗。稍后测试和更改会更容易。此外,这种方法几乎没有缺点(性能方面)。将两个史诗结合起来可以增加抽象而不知道它是否真的有必要。

另外,由看起来它的鸭子,这两个(侧面)效果的领域是不同的。我想说这是一个强有力的指标,使用单独的史诗在这里是一个好主意,并且会更有前途。这就是说,如果你确定你的史诗不会改变或者变得更加复杂(目前是if/else),我想这也没关系。


采取了第二次看后,我想你想要做的是“如果用户没有登录,显示我是一个登录页面,等到他(她)的登录和登录成功后,发起RSVP行动“。如果这是你的用例,你可能想看看delayWhen。这可能是更好的解决方案,但它更像是RxJS的高级功能。也许这是一个很好的重构任务,当你更加适应redux-observables :)

3

塞巴斯蒂安给出了很好的建议,通常我会分裂它们并复制逻辑。然而,如果你真的做了很多,你可以创建自己的抽象,所以你不需要重复自己。

您可以创建一个像requireAuth这样的助手,它会采取您期望的操作,以及一个只有在有效的身份验证时才会接收这些操作的史诗。然后它会返回一个包装它的新史诗。

// Helper to abstract the common auth requirement checks 
// which will also dispatch authenticationActions.show() 
// when they attempt to do something they can't 
const requireAuth = (type, epic) => (action$, store) => { 
    // matching actions which they have permission for 
    const valid$ = action$ 
    .ofType(type) 
    .filter(() => store.getState().user.signedIn); 

    // matching actions they do NOT have permission for 
    const invalid$ = action$ 
    .ofType(type) 
    .filter(() => !store.getState().user.signedIn); 

    return Observable.merge(
    epic(valid$, store), 
    invalid$.map(action => authenticationActions.show()) 
); 
}; 

const searchUsersEpic = requireAuth(scheduleActions.ADD_RSVP, (action$, store) => 
    action$.map(action => scheduleActions.rsvpAdded(action.payload)) 
); 

// You can then use requireAuth for any epics that require it 
// as an example: 
const searchMoviesEpic = requireAuth(scheduleActions.SEARCH_MOVIE, (action$, store) => 
    action$.mergeMap(action => 
    ajax(`/search/for/the/movie/${action.id}`) 
     .map(resp => scheduleActions.searchMoviesFulfilled(resp)) 
) 
); 

根据需要调整 - 但要小心,将抽象可以使你的代码难以以后理由或引入错误,当有人后来调整的抽象没有意识到它如何影响其他codepaths。

相关问题