【问题标题】:Where to put business logic in redux? action or storeredux 中的业务逻辑应该放在哪里?行动或商店
【发布时间】:2017-10-06 11:48:39
【问题描述】:

我从 Reflux 来到 Redux。在 Reflux 中,您的业务逻辑仅存在于商店中,但在 Redux 中它似乎不同..例如在“Redux”中我有 “async-action”,我用“redux-thunk”实现了它。

在一种情况下,我想检查我的操作中的某些内容,如果需要,我向服务器发送请求并获取一些数据。在这种情况下,我必须检查我的操作中的逻辑,实际上我的业务逻辑存在于操作中并存储在一起,它不好..你的解决方案是什么?

例如,我有复选框,我检查了一些条件,如果结果为真,我向服务器发送请求,这是我的操作代码,正如您所见,我的业务逻辑在我的 Action 和 Reducer 上:

export function onCheckboxClick({itemId}) {
  return (dispatch, getState) => {
      let state = getState().get('myReducer');

      let myConditionResult = state.get('foods').get(0).get('test');//for exmaple check some condition in my store

      dispatch({type: 'CHECKBOX_CLICK', itemId});// for change the checkbox checked

      if (myConditionResult) {
        myApi.deleteOrderItem({itemId}).then(()=> {
          dispatch({type: 'DELETE_ORDER_ITEM_FULFILLED', itemId});
        }).catch((err)=> {
          console.log(err);
          dispatch({type: 'DELETE_ORDER_ITEM_REJECTED', itemId});
        });
      }
   };
}

提前致谢

【问题讨论】:

  • 在您发送一个发出 http 请求的操作之前,请更具体地说明必须满足哪些条件?
  • @meteorBuzz 感谢您的回复我更新了我的问题

标签: redux redux-thunk refluxjs


【解决方案1】:

引用Redux FAQ entry on "how to split business logic between action creators and reducers"

对于 reducer 或 action creator 中应该包含哪些逻辑,没有一个明确的答案。

如果你把所有的逻辑都放在动作创建器中,你最终会得到声明状态更新的胖动作对象。 Reducers 变得纯粹、愚蠢、添加这个、删除那个、更新这些功能。他们将很容易组成。但是你的业务逻辑并不多。如果你在 reducer 中加入更多逻辑,你最终会得到漂亮、精简的 action 对象,大部分数据逻辑都在一个地方,但是你的 reducer 更难组合,因为你可能需要来自其他分支的信息。你最终会得到大型 reducer 或从 state 更高层获取额外参数的 reducer。

调度一个被reducer忽略的动作是有效的,首先检查状态并决定调度一个动作也是有效的。归根结底,这确实取决于您对什么感到满意。

【讨论】:

    【解决方案2】:

    如前所述,有多种方法可以执行此操作,具体取决于您的用例。我能做的就是列出你从推测你的用例中看起来更合适的东西。

    1.组件内部的逻辑。

    可以通过使用 connect from react-redux 将状态映射到 props 将保持条件的状态带入组件

    您还可以将动作导入此组件文件并将动作映射到道具。

    下面的示例演示了如何将状态和操作带入组件文件。你如何使用它取决于你。我把它放在一个简单的上下文中。所以你可以在你希望执行逻辑的时候调用myFunction()

    MyComponent.js

    import React, { Component} from 'react'
    import { connect } from 'react-redux'
    import { onCheckboxClick } from 'path/to/action'
    
    class MyComponent extends Component {
    
        myFunction() {
             const { theConditiion, onCheckboxClick } = this.props
    
             if (theConditiion) {
                 onCheckboxClick({itemId: 'someItemid'})
             }
        }
    
        render() {
          //...
        }
     }
    
    
    const mapStateToProps = (state) => ({
        theCondition: state.wherever.the.data.lives.in.store
    })
    
    export default connect(
        mapStateToProps,
        { onCheckboxClick }
        )(MyComponent)
    

    因此,对于上面的示例,您可以删除当前在 onCheckboxClick 函数中的条件检查。

    2。将逻辑放入中间件。

    下面的示例演示了如何调度动作,但首先,“捕捉”特定类型的动作,假设条件为真,您可以进行 api 调用并调度进一步的动作,如果为假,只需将动作传递给下一个中间件。

    myMiddleware.js

    const onCheckboxClick = store => next => action => {
        if (action.type == 'CHECKBOX_CLICK') {
    
        let theConditiion = store.getState().wherever.the.data.lives.in.store
    
        if (theConditiion) {
            // 1. make the api call here, or,
            // 2. dispatch an action specific to handling api calls.
            // E.g. Create another middleware to catch action type `API_CALL` 
            // This middleware can then handle all api calls, and dispatch actions for api requests, responses and errors. 
    
            const newAction = {...action, type: 'API_CALL' }
            store.dispatch(newAction)
    
            // When you use store.dispatch(), the action will be passed back to the top of the middleware chain. 
        }
    
        return next(action) // this will pass the action to the next middleware in the chain.
    
    }
    
    export default onCheckboxClick
    

    这是一个广泛的概述,可帮助您思考最有效的方法。请记住,随着您的应用程序的开发,您会注意到可以将重复的逻辑变成其自己的功能。

    【讨论】:

      【解决方案3】:

      这里有一些固执己见的答案,与 redux 的建议背道而驰。

      TL;DR 两者都没有

      更长的答案:在从中间件调用的所谓异步操作中。在 redux 社区中,它被称为“thunk”或“saga”。

      首先,一些定义:

      • action:一个普通的对象{ type: 'ACTION_TYPE', payload: { data } }
      • action creator:返回action的函数。
      • 异步操作:从中间件调用的函数。
      • async action creator:返回async action的函数
      • 中间件:一个可以处理所有动作、调度其他动作并可以访问存储状态的函数。

      那么,我们从哪里调用业务逻辑呢?

      如果您仔细观察,您会发现我们不需要 async actionasync action creator。我们可以有一个简单的action,直接在middleware中处理。

      middleware中,我们可以为每个action设置一个专用的handler。这个 handler 的行为类似于 async action,但我们不这么称呼它。我们称之为interactor

      所以一个新的定义:

      interactor:对 redux 中本质上是 async action 的抽象,但不是 redux 特定的。 Interactor 获取数据、调用业务逻辑并分派结果“动作”。

      middleware = (...) => {
        // if(action.type == 'HIGH_LEVEL') 
        interactors[action.name]({ dispatch, params: action.payload })
      }
      
      const interactors = {
        async highLevelAction({ dispatch, params }) {
          dispatch({ loading: true });
          const data = await api.getData(params.someId);
          const processed = myPureLogic(data);
          dispatch({ loading: false, data: processed });
        }
      }
      

      如何发送:

      dispatch({ type: 'HIGH_LEVEL', name: 'highLevelAction', { someId: 1 } })
      

      【讨论】:

      猜你喜欢
      • 2016-12-18
      • 2012-07-16
      • 2017-08-11
      • 1970-01-01
      • 2011-06-28
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      相关资源
      最近更新 更多