Oleksiï Nikonov
Oleksiï Nikonov

Reputation: 5598

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

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

Upvotes: 26

Views: 24115

Answers (9)

Ammad Ahmed
Ammad Ahmed

Reputation: 19

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);
    }
  }
);

Upvotes: 0

alambratoor
alambratoor

Reputation: 13

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

Upvotes: 0

Chidiebere Ezeokwelume
Chidiebere Ezeokwelume

Reputation: 139

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}) => {});

Upvotes: 0

Walker
Walker

Reputation: 954

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.

Upvotes: 2

Seif
Seif

Reputation: 46

make it this way

const  {pending,fulfilled,rejected} = fetchCountries
    builder.addCase(pending, isFetching);
    builder.addCase(rejected, error);
    builder.addCase(fulfilled, (state, action) => {});

Upvotes: 0

Bruno
Bruno

Reputation: 164

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.

Upvotes: 6

Oleksi&#239; Nikonov
Oleksi&#239; Nikonov

Reputation: 5598

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 ({ } => {})

Upvotes: 70

Anuj
Anuj

Reputation: 71

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}) => {});

Upvotes: 4

Proau
Proau

Reputation: 91

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"

Upvotes: 2

Related Questions