Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to put business logic in redux? action or store

i come from Reflux to Redux. in Reflux your business logic is exist only in store but in Redux its seems different..for example in "Redux" i have "async-action" and i implemented it with "redux-thunk" .

in one scenario i want to check something in my action and if that needed i send request to server and get some data. i this case i have to check my logic in my action and actually my business logic is exist in action and store together and its not good.. what is your solution?

for example i have checkbox and i check some condition and if the result is true i send a request to server here is my action code and as you see my business logic is on my Action and my 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});
        });
      }
   };
}

thanks in advance

like image 508
hossein derakhshan Avatar asked May 08 '17 12:05

hossein derakhshan


People also ask

Where do I put logic in Redux?

1. Logic inside the Component. You also import the action into this component file and map the action to props as well.

Should I put logic in reducer?

As of 2020, we specifically recommend putting as much logic as possible in reducers: Wherever possible, try to put as much of the logic for calculating a new state into the appropriate reducer, rather than in the code that prepares and dispatches the action (like a click handler).

What can I store in Redux store?

You store the state of your app in redux. How you structure your state tree is up to you. You can think of the state tree as one giant javascript object. With redux, you would ideally store as little component state in your react components themselves and instead move that to the redux state tree.

Should everything be stored in Redux?

Some users prefer to keep every single piece of data in Redux, to maintain a fully serializable and controlled version of their application at all times. Others prefer to keep non-critical or UI state, such as “is this dropdown currently open”, inside a component's internal state. Using local component state is fine.


2 Answers

Quoting the Redux FAQ entry on "how to split business logic between action creators and reducers":

There's no single clear answer to exactly what pieces of logic should go in a reducer or an action creator.

If you put all the logic in the action creator, you end up with fat action objects that declare the updates to the state. Reducers become pure, dumb, add-this, remove that, update these functions. They will be easy to compose. But not much of your business logic will be there. If you put more logic in the reducer, you end up with nice, thin action objects, most of your data logic in one place, but your reducers are harder to compose since you might need info from other branches. You end up with large reducers or reducers that take additional arguments from higher up in the state.

It's valid to dispatch an action that gets ignored by the reducers, and it's also valid to inspect the state first and decide to not dispatch an action. Ultimately, it does come down to what you're comfortable with.

like image 92
markerikson Avatar answered Sep 18 '22 21:09

markerikson


Here's some opinionated answer which goes against redux recommendations.

TL;DR Neither

Longer answer: in so called async action invoked from middleware. In redux community it is known as "thunk" or "saga".

First, some definitions:

  • action: a plain object { type: 'ACTION_TYPE', payload: { data } }
  • action creator: a function that returns action.
  • async action: a function that is called from middleware.
  • async action creator: a function that returns async action
  • middleware: a function which can handle all actions, dispatch other actions and has access to store state.

So, where do we call the business logic from?

If you look carefully, you'll notice that we don't need async action and async action creator. We can have a simple action that is handled directly in the middleware.

In middleware we can have a dedicated handler for each action. This handler behaves like async action but we don't call it so. Let's call it interactor.

So a new definition:

interactor: an abstraction of what is essentially async action in redux, but not redux-specific. Interactor fetches data, calls business logic and dispatches result "actions".

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

How to dispatch it:

dispatch({ type: 'HIGH_LEVEL', name: 'highLevelAction', { someId: 1 } })
like image 12
Vanuan Avatar answered Sep 21 '22 21:09

Vanuan