redux-actions library to refactor a counter example in Typescript errors

74 views Asked by At

I am new to Typescript and wanted to practice a library called redux-actions. I followed this tutorial:

https://youtube.com/watch?v=8DH7Ekp2PWI&feature=shares

and I tried to use the redux-actions tutorial

https://redux-actions.js.org/introduction/tutorial

but it does not work in jsfiddle or codepen, like they suggest, so I thought a better approach would be to modify the Youtube tutorial and use the redux-actions library in the codebase from the YouTube video.

The codebase for the Youtube tutorial is on github.

https://github.com/Jon-Peppinck/react-redux-ts

However, I am having trouble with the actions and reducer components. Here is what I have tried

Counter.ts

export interface Counter {
    count: number;
}

CounterActions.ts

import { createActions } from "redux-actions";

export const { increment, decrement } = createActions({
  INCREMENT: (amount = 1) => ({ amount }),
  DECREMENT: (amount = 1) => ({ amount: -amount }),
});

interface IncrementAction {
  type: typeof increment;
}

interface DecrementAction {
  type: typeof decrement;
}

export type CounterActionTypes = IncrementAction | DecrementAction;

CounterReducer.ts

import { handleActions } from "redux-actions";

import { CounterActionTypes, decrement, increment } from "./CounterAction";
import { Counter } from "./models/Counter";

const defaultState: Counter = {
  count: 0,
};

export const counterReducer = handleActions(
  {
    [increment]: (state: Counter, { payload: { amount } }: any): Counter => {
      return { ...state, count: state.count + amount };
    },
    [decrement]: (state: Counter, { payload: { amount } }: any): Counter => {
      return { ...state, count: state.count + amount };
    },
  },
  defaultState
);

But the increment and decrement actions are showing an error:

A computed property name must be of type 'string', 'number', 'symbol', or 'any'.ts(2464)

I am also not sure of the way I have typed the payload using any, is there a better way to type it. How can I fix my code and prevent the errors? Also, are there any resources or tutorials on using redux-actions that are not paid content. I searched, but I am unable to find anything.

2

There are 2 answers

0
ra100 On BEST ANSWER

Seems the issue is in the [increment], I don't get why it's that way in the documentation, but hey, it's 4 years old.

But what worked for me is this: CounterActions.ts

import {createActions} from 'redux-actions'

export interface ActionPayload {
  amount: number
}

export enum ActionNames {
  INCREMENT = 'increment',
  DECREMENT = 'decrement',
}

export const {increment, decrement} = createActions<ActionPayload>({
  [ActionNames.INCREMENT]: (amount = 1) => ({amount}),
  [ActionNames.DECREMENT]: (amount = 1) => ({amount: -amount}),
})

interface IncrementAction {
  type: typeof increment
}

interface DecrementAction {
  type: typeof decrement
}

export type CounterActionTypes = IncrementAction | DecrementAction

CounterReducer.ts

import {handleActions} from 'redux-actions'

import {ActionNames, ActionPayload} from './CounterAction'
import {Counter} from './models/Counter'

const defaultState: Counter = {
  count: 0,
}

export const counterReducer = handleActions<Counter, ActionPayload>(
  {
    [ActionNames.INCREMENT]: (state, {payload: {amount}}) => {
      return {...state, count: state.count + amount}
    },
    [ActionNames.DECREMENT]: (state, {payload: {amount}}) => {
      return {...state, count: state.count + amount}
    },
  },
  defaultState
)
2
markerikson On

I'm a Redux maintainer.

Please do not use redux-actions!

It's outdated, and using it will require writing a lot of code that you don't need to write.

Instead, today you should be using our official Redux Toolkit package. RTK has been designed to simplify and standardize Redux usage patterns, and also work great with TypeScript.

Here's what your example would look like with RTK (and an extra case reducer as a bonus):

// File: src/features/counterSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit"

interface CounterState {
  value: number;
}

const initialState : CounterState = {
  value: 0
}

const counterSlice = createSlice({
  name: "counter",
  initialState,
  // The `reducers` field lets us define reducers and generate associated actions
  reducers: {
    increment: (state) => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. It
      // doesn't actually mutate the state because it uses the Immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    }
  }
})

export const {
  increment, 
  decrement, 
  incrementByAmount
} = counterSlice.actions;

export default counterSlice.reducer

Please see our docs for details on how and why to use Redux Toolkit: