DEV Community

Utkal
Utkal

Posted on

Redux: Switching to other case within the same reducer

I am new to Redux. I am building a game with it. I know that reducers are there to react to actions thrown at them, by changing the state. In my reducer, I have 2 cases:
1) a switch case that needs to change the protagonist's state according to the data entry.
2) an error switch case, that sets the state's error attribute.

`export const movementReducer = (state=initial_state, action) => {

switch(action.type) {
    case "moveObject": {
         const new_position = ChangePosition(action.payload);
         return {
             ...state,
             position: new_position
         };
    }
    case "moveObjectError": {
         return {
             ...state,
             error: action.payload
         };
    }
}
Enter fullscreen mode Exit fullscreen mode

}`

What I want:-
When the control comes to "moveObject" case, it must first verify if this state change is feasible. If it is feasible, it must update. If it is not feasible, it must switch to the second case and set the Error.

What I tried:-
1) I believe this is a hack, makes the code not look good:-
If state change is not feasible for given input, I implicitly set the error and return it from the same case. The code looks like this:-

`
export const movementReducer = (state=initial_state, action) => {

switch(action.type) {
    case "moveObject": {
         if( !isMovementFeasible(state, action.payload)) {
              return {
                 ...state,
                 error: "This movement is not possible."
             };
         else {
             const new_position= ChangePosition(action.payload);
             return {
                 ...state,
                 position: new_position
             };
         }
    }
    case "moveObjectError": {
         return {
             ...state,
             error: action.payload
         };
    }
}
Enter fullscreen mode Exit fullscreen mode

}
`

This will work fine. But this did not actually trigger the "moveObjectError" action, which will be bad for tracking redux in future.

2) I can create an action creator, in it I can check for feasibility of movement. But then, I would have to access the state in action creator. I think this is not advised.

I want a way to trigger the "moveObjectError" case when movement is not feasible.

Top comments (3)

Collapse
 
vonheikemen profile image
Heiker

The quick way that I can think of is using recursion.

if(!isMovementFeasible(state, action.payload)) {
  return movementReducer(
    state,
    { type: 'moveObjectError', payload: 'Nop' }
  );
}

const new_position= ChangePosition(action.payload);
return {
  ...state,
  position: new_position  
}
Enter fullscreen mode Exit fullscreen mode

The "good" way would be creating a state machine inside your reducer. The good news is that the action.type can act as an event, so you only need to add a label to your state to make it work. The bad news is that it would involve some nesting conditionals so it may not look "elegant".

Collapse
 
nashmeyah profile image
Nashmeyah • Edited

What about redux thunk, it allows redux to perform async dispatches. Im not sure if this will help, but i suggested this because it seems when one of your dispatches if fired off youd like it to determine something wait for a response then finish the action.

github.com/reduxjs/redux-thunk

let me know if this was any useful, I am also curious.

Collapse
 
utkal97 profile image
Utkal

Hey, thanks for the response. I have thought of this approach before, this is what I have tried (#2 in "What I tried", perhaps I didn't mention Redux-thunk in the post). But we need to access the state in action creators, which I believe is not advised. If accessing state from action creators is considered ok, I am glad to go with it. I am pretty sure this solution works, but I want to code as per the good guidelines.