web-dev-qa-db-fra.com

Où mettre la logique métier dans Redux? action ou magasin

je viens de Reflux to Redux . dans Reflux, votre logique d’entreprise n’existe qu’en magasin, mais dans Redux cela semble différent..Par exemple, dans " Redux " j’ai "async-action" et j’ai mis en œuvre avec " redux-thunk ".

dans un scénario, je veux vérifier quelque chose dans mon action et si cela est nécessaire, j'envoie une demande au serveur et récupère des données. Dans ce cas, je dois vérifier ma logique dans mon action et, en fait, ma logique métier existe et est stockée ensemble. Ce n’est pas bon. Quelle est votre solution? 

par exemple, j'ai une case à cocher et je vérifie une condition et si le résultat est vrai, j'envoie une demande au serveur. Voici mon code d'action et, comme vous le voyez, ma logique métier est sur mon action et mon réducteur:

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});
        });
      }
   };
}

merci d'avance

9

Comme mentionné, il existe plusieurs façons d'effectuer cette action en fonction de votre cas d'utilisation. Ce que je peux faire, c'est vous énumérer ce qui semble plus approprié de spéculer sur votre cas d'utilisation.

1. Logique à l'intérieur du composant.

L'état qui contient la condition peut être importé dans le composant en le mappant aux accessoires à l'aide de connect from react-redux

Vous importez également l'action dans ce fichier de composant et mappez l'action aux accessoires également.

L'exemple ci-dessous montre comment vous amenez l'état et l'action dans le fichier de composant. Comment vous l'utilisez est à vous. Je l'ai mis dans un contexte simple. Vous pouvez donc appeler myFunction() au moment où vous souhaitez exécuter la logique.

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)

Par conséquent, vous pouvez supprimer les contrôles conditionnels que vous avez actuellement dans votre fonction onCheckboxClick pour l'exemple ci-dessus.

2. Insertion de logique dans le middleware.

L'exemple ci-dessous montre comment vous pouvez envoyer des actions, mais vous devez tout d'abord "capturer" un type d'action particulier, étant donné qu'une condition est vraie, vous pouvez effectuer un appel à l'API et envoyer d'autres actions. S'il est faux, transmettez simplement l'action. au middleware suivant. 

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

Ceci est un large aperçu pour vous aider à penser ce qui fonctionne le mieux. Gardez à l'esprit que, au fur et à mesure que votre application se développe, vous remarquerez que la logique répétée peut être transformée en ses propres fonctions. 

5
meteorBuzz

Citation de l'entrée Redux FAQ sur "Comment répartir la logique métier entre créateurs d'action et réducteurs" :

Il n’existe pas de réponse claire et précise aux éléments de logique à utiliser dans un réducteur ou un créateur d’action. 

Si vous mettez toute la logique dans le créateur d'action, vous vous retrouvez avec des objets d'action gras qui déclarent essentiellement les mises à jour de l'état. Les réducteurs deviennent purs, idiots, ajoutez-cela, supprimez-les, mettez à jour ces fonctions. Ils seront faciles à composer. Mais peu de votre logique commerciale sera là. Si vous mettez plus de logique dans le réducteur, vous vous retrouvez avec de beaux objets à action mince, la majeure partie de votre logique de données à un endroit, mais vos réducteurs sont plus difficiles à composer car vous pourriez avoir besoin d'informations provenant d'autres branches. Vous vous retrouvez avec de gros réducteurs ou des réducteurs qui prennent des arguments supplémentaires à partir des niveaux les plus élevés de l'état.

Il est valide d'envoyer une action qui est ignorée par les réducteurs, et d'inspecter d'abord l'état et de décider de non envoyer une action. En fin de compte, tout dépend de ce avec quoi vous êtes à l'aise.

10
markerikson

Voici une réponse éclairée qui va à l’encontre des recommandations de redux.

TL; DR Ni l'un ni l'autre

Réponse plus longue: dans l'action dite asynchrone invoquée à partir de middleware . Dans la communauté redux, il est connu sous le nom de "thunk" ou "saga".

Tout d'abord, quelques définitions:

  • action : un objet simple { type: 'ACTION_TYPE', payload: { data } }
  • action creator : une fonction qui retourne action .
  • action asynchrone : une fonction appelée à partir de middleware .
  • créateur d'action asynchrone : une fonction qui renvoie action asynchrone
  • middleware : fonction capable de gérer toutes les actions, d'envoyer d'autres actions et d'accéder à l'état du magasin.

Alors, où appelons-nous la logique métier?

Si vous regardez attentivement, vous remarquerez que nous n’avons pas besoin de action async et créateur d’action async . Nous pouvons avoir un simple action qui est traité directement dans le middleware .

Dans middleware nous pouvons avoir un handler dédié pour chaque action . Ce handler se comporte comme une action asynchrone mais nous ne l'appelons pas ainsi. Appelons cela interactor .

Donc une nouvelle définition:

interactor : une abstraction de ce qui est essentiellement action asynchrone dans redux, mais pas spécifique à redux. Interactor extrait les données, appelle la logique métier et distribue les "actions" des résultats.

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 });
  }
}

Comment l'envoyer:

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