1

Suppose that I have these 2 actions (as an example) for "creating category" and "loading all categories". I need to load all categories every time I create a new category successfully, so, I need to call "loadAllCategories" action within "createCategory". I usually do that like this while using TypeScript with Redux:

// Loading all categories
export const loadAllCategories = () => async (dispatch: Dispatch) => {

    try {

        // omitted for brevity

        dispatch<ILoadAntdTreeSelectCompatibleCategoriesAction>( {
            type: TaxonomyActionTypes.LOAD_ANTD_TREESELECT_COMPATIBLE_CATEGORIES,
            payload: {
                catTreeSelectLoading: false,
                catTreeSelectRegistry
            }
        })


    } catch (error) {

        // omitted for brevity

    }
}

// Creating a category
export const createCategory = (taxonomy: ITaxonomy) => async (dispatch: Dispatch) => {
    
    try {
        await agent.Taxonomies.create(taxonomy);

        dispatch<any>(loadAllCategories());    <--- Dispatching above action within this one

        dispatch<ICreateCategoryAction>({
            type: TaxonomyActionTypes.CREATE_CATEGORY,
            payload: {
                loadingInitial: false
            },
        })

    } catch (error) {
        // omitted for brevity
    }
}

I wanted to know, using dispatch with "any" type is the only way to call another action within the current one or there is a better way of doing that?

Could I use a more specific type instead of "any"?

Needless to say without using dispatch(action), just by calling the action's name it doesn't change the state so we have to use dispatch.

What is the best practice for doing that?

Aspian
  • 1,865
  • 3
  • 24
  • 31

1 Answers1

0

There is a simpler way to do this when you create a category lets say you use an API for that, make that API return the value you added, in response, then add that category to category list in Redux. use the following function in the reducer.

const addToList = (oldList:any, doc:any) => {
  let newList:any = oldList;
  newList.push(doc);

  return newList;
}

and in the reducer function call it like

case TaxonomyActionTypes.CREATE_CATEGORY:
      return { ...state, categories: addToList(state.categories, action.payload) }

Edit

The Answer to your question is

dispatch<Array>

Example

interface Category {
  name: String,
}


let x:Array<Category>
  • 1
    The purpose of the question is knowing the best practice for calling an action within another in Redux with TypeScript. I just wanted to know could I use another more specific type instead of "any" for dispatch and that's all, although thank you. – Aspian Nov 28 '20 at 18:21
  • @Aspian Sorry, So getAllCategories will return a list, so can use the type Array to make it more type strict – mustafa.shykh Nov 28 '20 at 18:51
  • Thanks but the return type of "loadAllCategories" is a Promise because it is asynchronous and uses thunk so it dispatches something and doesn't return anything so the type is Promise. Ironically, we can't use this as dispatch's type because dispatch implements Dispatch interface of Redux and its default type is AnyAction like Dispatch but you cannot use it like this Dispatch> because Promise does not satisfy the constraint 'Action' in which property "type" is required. That's why I used the type "any" for dispatch. It works fine but it's a hack. – Aspian Nov 28 '20 at 20:02