如何通过Redux响应状态更改来触发AJAX调用? [英] How to fire AJAX calls in response to the state changes with Redux?

查看:205
本文介绍了如何通过Redux响应状态更改来触发AJAX调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将现有状态模型转换为Redux,并且在大多数情况下它很轻松.但是,我遇到的问题是转换观察到"状态的ajax请求.本质上,我有某些ajax请求链接"到其他状态,因此,无论是谁修改它们,它们都将始终正确发出.通过订阅Redux存储更新,我可以得到类似的行为,但是在侦听器中触发动作感觉就像是黑客.

I'm converting an existing state model to Redux and it has been painless for the most part. However the one point I'm having trouble with is converting "observed" state ajax requests. Essentially, I have certain ajax requests "linked" to other pieces of state, so no matter who modifies them they'll always be issued correctly. I can get similar behavior by subscribing to the Redux store updates, but firing actions in the listener feels like a hack.

一个可能的解决方案是通过thunk模式将逻辑移至动作创建者.问题是我要么必须跨动作复制获取逻辑(因为多个动作可以修改观察"状态),要么将大多数化简器逻辑拉到动作创建者级别.动作创建者也不应该知道减速器将如何响应已发布的动作.

A possible solution is to move logic to the action creator via the thunk pattern. Problem is that I'd either have to duplicate fetching logic across actions (since multiple actions could modify "observed" state), or pull most reducer logic to the action creator level. The action creator also shouldn't be aware of how the reducers will respond to issued actions.

我可以批处理子动作",因此我只需要在每个动作块"中放置适当的提取逻辑,但这似乎违反了产生有效状态的动作的概念.我宁愿在动作创建者级别承担此责任.

I could batch "sub-actions" so I only need to place the appropriate fetching logic in each action "block", but this seems to violate the concept of actions producing a valid state. I'd rather have this liability at the action creator level.

是否有关于此的普遍接受的规则?这不是一个简单的应用程序,在与组件交互时会发出临时的ajax请求,大多数数据在多个组件之间共享,并且会根据状态变化对请求进行优化和提取.

Are there any generally accepted rules surrounding this? This is not a simple application where ad hoc ajax requests are made as components are interacted with, most data is shared between multiple components and requests are optimized and fetched in reaction to state change.

TLDR; 我想触发ajax请求以响应状态变化,而不是在发生特定操作时触发.除了在订阅侦听器中触发这些动作之外,是否有更好的特定于Redux的"方式来组织action/actionCreator来模拟此行为?

TLDR; I want to fire ajax requests in response to changes in state, not when a specific action happens. Is there a better, "Redux specific" way of organizing action/actionCreators to mock this behavior, other than firing these actions in a subscribe listener?

推荐答案

使用store.subscribe()

最简单的方法是简单地使用store.subscribe()方法:

Using store.subscribe()

The easiest way is to simply use store.subscribe() method:

let prevState
store.subscribe(() => {
  let state = store.getState()

  if (state.something !== prevState.something) {
    store.dispatch(something())
  }

  prevState = state
})

您可以编写一个自定义抽象,让您注册副作用的条件,以便更明确地表达它们.

You can write a custom abstraction that lets you register conditions for side effects so they are expressed more declaratively.

您可能需要查看 Redux循环,它可以用来描述效果(例如AJAX )调用一起,并在化简器中进行状态更新.

You might want to look at Redux Loop which let you describe effects (such as AJAX) calls together with state updates in your reducers.

这样,您可以像对当前状态return的下一个状态一样,返回"这些效果以响应某些操作:

This way you can "return" those effects in response to certain actions just like you currently return the next state:

export default function reducer(state, action) {
  switch (action.type) {
    case 'LOADING_START':
      return loop(
        { ...state, loading: true },
        Effects.promise(fetchDetails, action.payload.id)
      );

    case 'LOADING_SUCCESS':
      return {
        ...state,
        loading: false,
        details: action.payload
      };

这种方法的灵感来自榆木架构.

您还可以使用 Redux Saga ,它允许您编写长时间运行的进程("sagas "),可以执行操作,执行一些异步工作,并投放结果操作到商店. Sagas会注意特定的操作,而不是状态更新,这不是您要求的,但我想我还是会提到它们,以防万一.它们对于复杂的异步控制流和并发非常有用.

You can also use Redux Saga that lets you write long-running processes ("sagas") that can take actions, perform some asynchronous work, and put result actions to the store. Sagas watch specific actions rather than state updates which is not what you asked for, but I figured I’d still mention them just in case. They work great for complicated async control flow and concurrency.

function* fetchUser(action) {
   try {
      const user = yield call(Api.fetchUser, action.payload.userId);
      yield put({type: "USER_FETCH_SUCCEEDED", user: user});
   } catch (e) {
      yield put({type: "USER_FETCH_FAILED",message: e.message});
   }
}

function* mySaga() {
  yield* takeEvery("USER_FETCH_REQUESTED", fetchUser);
}

没有一种正确的方法

所有这些选项都有不同的权衡.有时人们会使用一两个或三个,甚至是全部三个,这取决于最方便地测试和描述必要逻辑的内容.我鼓励您尝试所有这三种方法,并选择最适合您的用例的

 No One True Way

All these options have different tradeoffs. Sometimes people use one or two, or even all three of them, depending on what turns out to be most convenient for testing and describing the necessary logic. I encourage you to try all three and pick what works best for your use case.

这篇关于如何通过Redux响应状态更改来触发AJAX调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆