Redux 如何让多个reducer基于一组常见的操作触发更新,而不重复您自己的操作?

Redux 如何让多个reducer基于一组常见的操作触发更新,而不重复您自己的操作?,redux,Redux,我希望我的应用程序中有许多不同的redux操作,都能触发特定reducer中的通用功能。我希望避免在reducer寻找的每个动作创建者(比如doThing:true)中重复某些标志。我也不想让reducer只查找属于这一类的每个动作,因为这也要求有人在每次添加新动作时都要记住这样做,比如添加标志 我在考虑每次发送一个动作时都发送第二个动作。这并不难做到,但我不希望每次发生一件事时都调度两个动作。这似乎会污染国家历史 有解决这个问题的通用方法吗 关于我的具体问题的更多内容,具体功能与我的应用程序用

我希望我的应用程序中有许多不同的redux操作,都能触发特定reducer中的通用功能。我希望避免在reducer寻找的每个动作创建者(比如doThing:true)中重复某些标志。我也不想让reducer只查找属于这一类的每个动作,因为这也要求有人在每次添加新动作时都要记住这样做,比如添加标志

我在考虑每次发送一个动作时都发送第二个动作。这并不难做到,但我不希望每次发生一件事时都调度两个动作。这似乎会污染国家历史

有解决这个问题的通用方法吗

关于我的具体问题的更多内容,具体功能与我的应用程序用来与我们的API对话的API客户端有关。对于每个成功的响应,我们希望在一个reducer中做一些事情来更新状态,对于每个失败的响应,我们希望做一些其他的事情

有许多不同的成功和失败操作(如ITEM_FETCH_success或WIDGET_UPDATE_failure),在添加新操作时,很难记住要为所有操作添加一个标志


由于所有api请求都通过一个函数,因此该函数可以调度通用的请求成功和请求失败操作。但这意味着来自服务器的每个响应都将分派2个操作(REQUEST_SUCCESS和ITEM_FETCH_SUCCESS)。这显然不理想,因为这意味着在我的状态历史记录中会有更多的操作。

假设通用的
请求_成功
请求_失败
操作正在更新它们自己的状态树的特定部分,则可以将它们作为不同的操作进行调度。这样做并不一定意味着你的州历史受到污染,但可以更好地描述应用的意图

  • 项目获取成功
    :更改
    项目的状态

  • REQUEST\u SUCCESS
    :更改请求的状态

  • 小部件\u更新\u失败
    :更改
    小部件的状态

  • 请求\u失败
    :更改请求的状态

您可以看到,虽然这些操作密切相关,但它们不一定是同一件事,因为它们改变了状态树的不同部分

接受这一点,问题是:如何最好地实现动作对,以便添加新动作并不意味着记住添加相应的
REQUEST.*
partner

我会考虑应用一个简单的ReDux中间件组件。这可能会截获api的返回,并自动发送相应的
请求*
操作

下面是一些实时代码的示例。此中间件拦截websocket引发的
断开连接
事件,并因此自动分派自定义操作。它至少显示了以下原则:

//Dispatch a disconnect action when the websocket disconnects
//This is the custom action provided by the middleware

import io from 'socket.io-client'
import { actions } from './action'

const websocket = ({ websocketUrl }) => store => {
  const socket = io(websocketUrl)
  socket.on('disconnect', () => store.dispatch(actions.disconnect()))
}

export default websocket



此实现将所有内容都保存在还原程序中,而不是将逻辑放在拦截(中间件)的外部。两种方法都有效。

尝试使用副减速器模式。当我看到它被使用时,我通常会感到恶心(因为它通常被错误地使用),但你的情况听起来很完美

  • 将简化程序中的重复功能提取到一个 副减速器
  • 然后将该减速器作为函数传递给所有其他需要它的人
  • 然后将动作和状态传递到副减速器上
  • sub-reducer执行它的操作,并将该状态片返回给 你的父母允许你用它做任何你想做的事 那里(返回它,再变异一些,再变异一些逻辑)
  • 这也是可能的,一种简单的方法是将每一个动作都交给一个还原剂,让它在单一情况下进行普通突变:

    case actionOne
         actionTwo 
         actionThree
         actionFour: { 
           //do common stuff here
         }
    

    。但是你说它不是重复的,它是相似的,这意味着你的案例会因为分支逻辑而变得复杂。我也不推荐这个。保持病例简单,以便轻松捕获无效突变这应该是redux的强大功能,它很容易捕捉到突变错误。出于这个原因以及其他许多原因,我不建议在前端对数据进行规范化。

    我不确定我是否同意不同的还原器需要不同的操作部分。例如,如果我在启动时调度了一个app_加载的操作,并且需要多个reducer根据app_加载数据初始化它们的状态,那么当我可以让所有reducer都侦听一个app_加载的操作时,我不想为每个reducer调度一个操作。这里的问题似乎是,我希望多个还原程序侦听多个操作,这与init示例不同。当多个还原程序听一个动作时,让每个还原程序的动作分开似乎更简单,但我相信redux的作者Dan Abramov说,这并不是redux使用的必然方式。一个动作可以跨多个还原器使用,尤其是在数据已被规范化/非规范化的情况下。我同意,在不同的还原器中对同一动作进行不同的解释是完全正确的。对于状态的不同更改,可以使用不同的操作。后者本身不是“污染”,但可以更好地描述应用的意图。我编辑了简介,使之更清楚。谢谢。不过实际上没有任何重复的功能。itemsReducer可能会在发送itemsFetchSuccessful操作时设置处于状态的项列表。需要了解所有不同成功和失败的减速器保持一个全局状态。它与c所列的项目无关
    // Create the top-level redux store passing in the custom middleware enhancer
    
    const opts = {websocketUrl: env.WEBSOCKET_URL}
    const store = createStore(reducers, websocketize(opts))
    
    case actionOne
         actionTwo 
         actionThree
         actionFour: { 
           //do common stuff here
         }