createAsyncThunk: Error: addCase cannot be called with two reducers for the same action type
Asked Answered
A

9

26

This error occurred when I connect actions to extraReducers My code is

export const fetchCountries = createAsyncThunk(
  `country`, 
  async (organizationId: string) => {

export const saveCountry = createAsyncThunk(
  `country`,
  async ({ } => {})

const regions = createSlice({
  name,
  initialState,
  reducers: {},
  extraReducers: builder => {
    builder.addCase(fetchCountries.pending, isFetching);
    builder.addCase(fetchCountries.rejected, error);
    builder.addCase(fetchCountries.fulfilled, (state, action) => {});

    builder.addCase(saveCountry.pending, isFetching);
    builder.addCase(saveCountry.rejected, error);
    builder.addCase(saveCountry.fulfilled, (state, {payload}) => {});

and if I run I get this error: Error: addCase cannot be called with two reducers for the same action type

Align answered 14/7, 2021 at 9:24 Comment(0)
A
68

This happens because in my actions there is few AsyncThunks actions with the same typePrefix.

So it must have different names:

export const fetchCountries = createAsyncThunk(
  `getCountry`, //<------ this first argument (name) must be unique
  async (organizationId: string) => {

export const saveCountry = createAsyncThunk(
  `postCountry`,
  async ({ } => {})

Align answered 14/7, 2021 at 9:24 Comment(1)
Thanks for helping reduce time required to find a thunk copy-paste mistake :)Antitank
A
6

In my case, the same error message was show, but it was a different mistake:

.addCase(setAddress.pending, (state, action) => {
    state.setAddressStatus = 'Pending';
})
.addCase(setAddress.fulfilled, (state, action) => {
    state.setAddressStatus = 'Fulfilled';  
})
.addCase(setAddress.fulfilled, (state, action) => { // I repeated fulfilled 
    state.getAddressesStatus = 'Rejected';
    console.error(action.error);
})
            

It took me some minutes to find the problem, may help someone.

Ari answered 21/5, 2022 at 17:42 Comment(0)
N
4

On CreateAsycThunk you have mentioned both the string of the same name it should be like this

export const fetchCountries = createAsyncThunk(
  `country`, 
  async (organizationId: string) => {

export const saveCountry = createAsyncThunk(
  `saveCountry`,
  async ({ } => {})

const regions = createSlice({
  name,
  initialState,
  reducers: {},
  extraReducers: builder => {
    builder.addCase(fetchCountries.pending, isFetching);
    builder.addCase(fetchCountries.rejected, error);
    builder.addCase(fetchCountries.fulfilled, (state, action) => {});

    builder.addCase(saveCountry.pending, isFetching);
    builder.addCase(saveCountry.rejected, error);
    builder.addCase(saveCountry.fulfilled, (state, {payload}) => {});
Navigable answered 29/4, 2022 at 4:17 Comment(2)
how your answer differs from mine?Align
It looks like the difference is both are named `country` in the question and here one is labeled `country` and the other `saveCountry`Caribou
L
2

createasyncthunk has two main parameters, one of type string and the latter callback function which has api and thunk as paramters. You are likely to be pardon if having a single asyncthunk in your slice, which has "" as data, but if you have two or more asyncthunks then checks will be made on each thunk, if two or more of them has similar "" or "identical" names then you will get disturbing error. "createAsyncThunk: Error: addCase cannot be called with two reducers for the same action type"

Lascivious answered 20/2, 2022 at 14:10 Comment(0)
D
1

If your createAsnyncThunk is using the same typePrefix like

const updateEventsCal = createAsyncThunk(
EVENTS_CAL_UPDATE, // using an existing typePrefix say EVENTS_CAL_ADD
async (data) => {
 }

This will throw the same error.

Drugi answered 22/6, 2023 at 18:44 Comment(0)
N
0

make it this way

const  {pending,fulfilled,rejected} = fetchCountries
    builder.addCase(pending, isFetching);
    builder.addCase(rejected, error);
    builder.addCase(fulfilled, (state, action) => {});
Nostrum answered 3/1, 2023 at 23:12 Comment(0)
C
0

You are having this error because you are attempting to add multiple asyncthunks with the same typePrefix ie the first argument in the createAsyncthunk. Each asyncthunk must have a unique typePrefix. To resolve this you simply create a unique typePrefix for each createAsyncthunk

export const fetchCountries = createAsyncThunk(
  `fetch-country`, 
  async (organizationId: string) => {

export const saveCountry = createAsyncThunk(
  `save-country`,
  async ({ } => {})

You can also have the same error message when you try to add multiple reducers for the same action type using the addCase function ie

const regions = createSlice({
  name,
  initialState,
  reducers: {},
  extraReducers: builder => {
    builder.addCase(fetchCountries.pending, isFetching);
    builder.addCase(fetchCountries.rejected, error);
    builder.addCase(fetchCountries.fulfilled, (state, action) => {});
    
    builder.addCase(fetchCountries.fulfilled, (state, action) => {});
 
    builder.addCase(saveCountry.pending, isFetching);
    builder.addCase(saveCountry.rejected, error);
    builder.addCase(saveCountry.fulfilled, (state, {payload}) => {});
Convulsion answered 8/7, 2023 at 14:3 Comment(0)
K
0

i had the same problem,have a look below:

//api to get data customers
export const getCustomers = createAsyncThunk('/api/users/customers',async() =>{
    ...
});
//api to add customer
export const addCustomer = createAsyncThunk<User,{ user: User, token: string }>('/api/users/add_customer', async ({ user, token }) => {
    ...
});

i got the problem cuz i wrote this path /api/users/customers in frist and second asyncthunk, to solve it ,just need to rename it, in my case, first i didn't change it /api/users/customers and second /api/users/add_customer

Karelia answered 7/8, 2023 at 18:30 Comment(0)
R
0

In my case, I was facing this error because of using same action names of asyncThunk. ("orders/fetchOrders") in both functions

First I will show the mistake I was doing is following, check the action names. Both are same mistakenly.

 export const fetchOrders = createAsyncThunk("orders/fetchOrders", async () => {
  try {
    const querySnapshot = await getDocs(
      query(collection(db, "orders"), orderBy("createdAt", "desc"))
    );
    const orders = querySnapshot.docs.map((doc) => ({
      id: doc.id,
      ...doc.data(),
    }));
    console.log(orders);
    return orders;
  } catch (error) {
    return Promise.reject(error);
  }
});
export const updateOrderStatus = createAsyncThunk(
  "orders/fetchOrders",
  async ({ orderId, newStatus }) => {
    try {
      console.log(orderId, newStatus);
      const orderRef = doc(db, "orders", orderId);
      await updateDoc(orderRef, {
        status: newStatus,
        updatedAt: Timestamp.now().toDate(),
      });
      toast.success("Order status updated successfully");
    } catch (error) {
      toast.error(error.message);
    }
  }
);

Just keep the action names different

 export const fetchOrders = createAsyncThunk("orders/fetchOrders", async () => {
  try {
    const querySnapshot = await getDocs(
      query(collection(db, "orders"), orderBy("createdAt", "desc"))
    );
    const orders = querySnapshot.docs.map((doc) => ({
      id: doc.id,
      ...doc.data(),
    }));
    console.log(orders);
    return orders;
  } catch (error) {
    return Promise.reject(error);
  }
});
export const updateOrderStatus = createAsyncThunk(
  "orders/updateOrderStatus",
  async ({ orderId, newStatus }) => {
    try {
      console.log(orderId, newStatus);
      const orderRef = doc(db, "orders", orderId);
      await updateDoc(orderRef, {
        status: newStatus,
        updatedAt: Timestamp.now().toDate(),
      });
      toast.success("Order status updated successfully");
    } catch (error) {
      toast.error(error.message);
    }
  }
);
Russia answered 19/4 at 12:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.