Home > Blockchain >  How to dispatch an action as a variable in React with TS?
How to dispatch an action as a variable in React with TS?

Time:10-09

How could I pass the type property as a parameter into a dispatch function?

type Actions = 
   | {type: 'addToBag', bagProducts: string[]}
   | {type: "increaseQty", prodName: string}
   | {type: "decreaseQty", prodName: string}

interface InitialState {
   bagProducts: string[]
}

const reducer = (state: InitialState, action: Actions): InitialState => {
   switch (action.type) {
      case 'addToBag':
         return {
            // something
         }
      case 'increaseQty':
         return {
            // something
         }
      case 'decreaseQty':
         return {
            // something
         }
      default: 
         return state
   }
}

const [cartProductsStateR, dispatch] = useReducer(reducer, initialState)

Dispatch function (how it is):

   const decreaseProductQty = (name: string) => {
      dispatch({type: 'decreaseQty', prodName: name})
   }

How want it to be:

   const decreaseProductQty = (name: string, action: string) => {
      dispatch({type: action, prodName: name})
   }

But if I do this I get this error on property type:

Type 'string' is not assignable to type '"addToBag" | "increaseQty" | "decreaseQty"'

I've tried this:

const decreaseProductQty = (name: string, action: "addToBag" | "increaseQty" | "decreaseQty") => {
   dispatch({type: action, prodName: name})
}

Then I got this error, but I don't get why?

Type '"addToBag" | "increaseQty" | "decreaseQty"' is not assignable to type '"addToBag" | "increaseQty" | "decreaseQty"'

Is there a wat where I could receive action as a parameter and pass it to dispatch instead of a plain string?

CodePudding user response:

It is giving error because your payloads are different types.

In the below case, what if action is "addToBag"? You can't have same payload "prodName" in all your actions.That is why TypeScript is complaining.

const decreaseProductQty = (name: string, action: "addToBag" | "increaseQty" | "decreaseQty") => {
   dispatch({type: action, prodName: name})
}

I would refactor your code to action creators like this:


   const addToBag = (bagProducts: string[]) => ({type: 'addToBag', bagProducts} as const)
   const increaseQty = (prodName: string) => ({type: 'increaseQty', prodName} as const)
   const decreaseQty = (prodName: string) => ({type: 'increaseQty', prodName} as const)


   type Actions = 
   | ReturnType<typeof addToBag>
   | ReturnType<typeof increaseQty>
   | ReturnType<typeof decreaseQty>


// later in a component
  const decreaseProductQty = (name: string) => {
      dispatch(decreaseQty(name))
   }
  • Related