【问题标题】:Conditionally fetching data in epic有条件地获取史诗中的数据
【发布时间】:2017-11-06 21:51:44
【问题描述】:

假设我有以下史诗:

const getPostsEpic = (action$, store) => {
    return action$.ofType(actionTypes.REQUEST_POSTS)
        .switchMap(action =>
            ajax.getJSON(`api/posts?key=${action.key}`)
            .map(response =>
                receivePosts({type: RECEIVE_POSTS, posts: response})
            ).takeUntil(
                action$.ofType(actionTypes.ABORT_GET_POSTS)
            )
};

说我的减速器是这样的

function reducer(
  state = {
    isFetching: false,
    didInvalidate: true,
    items: []
  },
  action
) {
  switch (action.type) {
    case INVALIDATE_POSTS:
      return Object.assign({}, state, {
        didInvalidate: true
      })
    case REQUEST_POSTS:
      return Object.assign({}, state, {
        isFetching: true,
        didInvalidate: false
      })
    case RECEIVE_POSTS:
      return Object.assign({}, state, {
        isFetching: false,
        didInvalidate: false,
        items: action.posts,
      })
    default:
      return state
  }
}

我想确保只有在我所在州的 didInvalidate === true 时才会获取帖子,有没有一种好方法可以让我的史诗作品能够实现这一目标?可以做这样的事情,但它不是那么漂亮的 IMO:

const getPostsEpic = (action$, store) => {
    return action$.ofType(actionTypes.REQUEST_POSTS)
        .switchMap(action => {
            const state = store.getState();
            if (state.didInvalidate) {
                return ajax.getJSON(`api/posts?key=${action.key}`)
                    .map(response =>
                        receivePosts({type: RECEIVE_POSTS, posts: response})
                    ).takeUntil(
                        action$.ofType(actionTypes.ABORT_GET_POSTS)
                )
            else {
                return Observable.of({type: RECEIVE_POSTS, posts: state.items});
            }
        }
};

顺便说一句,我正在将它与 React 一起使用。我确定这是一个很常见的问题,所以也许在我的史诗之外有更好的方法来处理这个问题?

【问题讨论】:

  • 也许我理解错了,但是如果 didInvalidate 为假,为什么还要发送 REQUEST_POSTS 呢?
  • @msolvaag,原因是我有不同的依赖于帖子数据的反应路线,我通常从不同组件的componentDidMount 分派REQUEST_POSTS。加载组件时,帖子可能已经加载,也可能尚未加载。我当然可以检查整个地方的isInvalidated 标志,但这似乎也不是最理想的。

标签: redux rxjs5 redux-observable


【解决方案1】:

您可以使用if 进行分支,如下所示:

const mockAjax = () => Promise.resolve({posts: [4, 5, 6, 7]});

const fetchPost = (action$) => Rx.Observable.fromPromise(mockAjax())
  .map(({posts}) => ({type: RECEIVE_POSTS, posts}))
  .takeUntil(action$.ofType(ABORT_GET_POSTS))

const defaultPosts = (action$, store) => Rx.Observable.of({type: RECEIVE_POSTS, posts: store.getState().items});

const getPostsEpic = (action$, store) =>
  action$.ofType(USER_REQUEST)
    .mergeMap(() => Rx.Observable.if(
      () => store.getState().didInvalidate, // condition
      fetchPost(action$), // if true
      defaultPosts(action$, store) // if false
    )
    .do(x => console.log(x))
)

查看她的演示:http://jsbin.com/jodaqopozo/edit?js,console,output

单击有效/无效按钮,然后单击“发布请求”将记录不同的值。

希望这会有所帮助。

【讨论】:

  • 这只是在成功的情况下分派,问题是关于根据 didInvalidate 分派不同的动作。
  • 我修改了代码以反映问题。我的错。
猜你喜欢
  • 2023-02-19
  • 2018-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-11
  • 2021-07-27
  • 2016-04-05
相关资源
最近更新 更多