将业务逻辑放在redux中的位置?行动或商店

hos*_*han 12 refluxjs redux redux-thunk

我来自RefluxRedux.在Reflux中你的业务逻辑只存在于商店中,但在Redux中它似乎不同......例如在" Redux "中,我有"async-action",我用" redux-thunk " 实现它.

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

例如我有复选框,我检查一些条件,如果结果是真的我发送请求到服务器这里是我的动作代码,因为你看到我的业务逻辑是在我的行动和我的减速机:

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});
        });
      }
   };
}
Run Code Online (Sandbox Code Playgroud)

提前致谢

mar*_*son 12

引用Redux FAQ条目"如何在动作创建者和减少者之间拆分业务逻辑":

对于减速器或动作创建者应该采用什么样的逻辑,没有一个明确的答案.

如果将所有逻辑放在动作创建器中,最终会生成基本上声明状态更新的胖动作对象.Reducers变得纯粹,愚蠢,添加 - 删除它,更新这些功能.它们很容易构成.但是你的业务逻辑并不多.如果你在reducer中加入了更多的逻辑,你最终会得到漂亮的瘦动作对象,大部分数据逻辑都集中在一个地方,但是你的reducer更难以编写,因为你可能需要来自其他分支的信息.你最终得到了大型减速器或减速器,它们从该州的较高位置获取额外的参数.

调度一个被reducers忽略的动作是有效的,并且首先检查状态并决定调度动作也是有效的.最终,它确实归结为您所熟悉的.


met*_*uzz 6

如上所述,根据您的使用情况,有多种方法可以执行此操作.我能做的就是列出你猜测你的用例似乎更合适的东西.

1.组件内的逻辑.

持有的条件的状态可通过状态映射到使用的道具被带入组分connect反应-终极版

您还可以将操作导入此组件文件,并将操作映射到props.

下面的示例演示了如何将状态和操作引入组件文件.你如何使用它取决于你.我把它放在一个简单的背景中.因此,您可以myFunction()在希望执行逻辑的位置调用.

MyComponenet.js

import React, { Component} from 'react'
import { connect } from 'react-redux'
import { onCheckboxClick } from 'path/to/action'

class MyComponenet extends Component {

    myFunction() {
         const { theConditiion, onCheckboxClick } = this.props

         if (theConditiion) {
             onCheckboxClick({itemId: 'someItemid'})
         }
    }

    render() {
      //...
    }
 }


const mapStateToProps = (state) => ({
    theConditiion: state.wherever.the.data.lives.in.store
})

export default connect(
    mapStateToProps,
    { onCheckboxClick }
    )(MyComponenet)
Run Code Online (Sandbox Code Playgroud)

因此,您可以删除onCheckboxClick函数中当前具有的条件检查,以用于上述示例.

2.将逻辑放在中间件中.

下面的示例演示了如何分配操作,但首先,"捕获"特定类型的操作,假设条件为真,您可以进行api调用并调度进一步的操作,如果为false,则只传递操作到下一个中​​间件.

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
Run Code Online (Sandbox Code Playgroud)

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


Van*_*uan 6

这是一些有争议的答案,与redux建议背道而驰。

TL; DR 均不

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

首先,一些定义:

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

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

如果仔细看,您会发现我们不需要异步动作异步动作创建者。我们可以有一个直接在中间件中处理的简单操作

中间件中,我们可以为每个动作提供专用的处理程序。该处理程序的行为类似于异步操作,但我们不这样称呼。我们称它为“ 交互器”

所以有一个新的定义:

交互器:在redux中实质上是异步操作的抽象,但不是特定于redux的。交互器获取数据,调用业务逻辑并调度结果“操作”。

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 });
  }
}
Run Code Online (Sandbox Code Playgroud)

如何发送:

dispatch({ type: 'HIGH_LEVEL', name: 'highLevelAction', { someId: 1 } })
Run Code Online (Sandbox Code Playgroud)