skip to Main Content

I have an array of incomes that I display in a table. There’s a "+" button to add a new income. I want to increment database and redux store with a dispatch.

Increment database works fine, but I have to reload page to see new data.

Why my dispatch does not update the state.data of incomes ?

// AddNewData.tsx
[...]
const onSubmit: SubmitHandler<FieldValues> = async (data) => {
        if (user) {
            const formData = {
                userId: user._id,
                label: data.label,
                amount: data.amountInput,
            };

            dispatch(addUserIncome(formData));
        }
    };
[...]
//incomes_slice.ts

import { IDataState, IEntry } from "../../helpers/Interfaces";
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { deleteData, getData, updateData, addData } from "../../APIs/UserData";
import { Notifier } from "../../helpers/Notifier";

const initialState: IDataState = {
    data: [],
    loading: false,
    error: null,
};

export const getUserIncomes = createAsyncThunk("incomes/getUserIncomes", (userId: string) => {
    return getData("incomes", userId);
});

export const addUserIncome = createAsyncThunk("incomes/addUserIncome", async (data: { userId: string; label: string; amount: number }) => {
    const response = await addData("incomes", data).then((res) => {
        const newEntry: IEntry = {
            _id: res.data.income._id,
            user: data.userId,
            label: data.label,
            amount: data.amount,
        };

        return newEntry;
    });

    return response;
});

export const updateUserIncome = createAsyncThunk("incomes/updateUserIncome", async (data: { id: string; data: IEntry }) => {
    await updateData("incomes", data.id, data.data);
    return data;
});

export const deleteUserIncome = createAsyncThunk("incomes/deleteUserIncome", async (incomeId: string) => {
    await deleteData("incomes", incomeId);
    return incomeId;
});

const incomesSlice = createSlice({
    name: "incomes",
    initialState,
    reducers: {},
    extraReducers: (builder) => {
        builder.addCase(getUserIncomes.pending, (state) => {
            state.loading = true;
        });
        builder.addCase(getUserIncomes.fulfilled, (state, action) => {
            state.loading = false;
            state.data = action.payload;
            state.error = null;
        });
        builder.addCase(getUserIncomes.rejected, (state, action) => {
            state.loading = false;
            state.error = action.error.message;
            action.error.message && Notifier(action.error.message, "error");
        });
        builder.addCase(addUserIncome.fulfilled, (state, action) => {
            state.data.push(action.payload);
        });
        builder.addCase(updateUserIncome.fulfilled, (state, action) => {
            state.data = state.data.map((income) => {
                if (income._id === action.payload.id) {
                    return action.payload.data;
                }
                return income;
            });
        });
        builder.addCase(deleteUserIncome.fulfilled, (state, action) => {
            state.data = state.data.filter((income) => income._id !== action.payload);
        });
    },
});

export const incomesReducer = incomesSlice.reducer;

PS: addData function is just an axios.post that works fine.

2

Answers


  1. Inside addUserIncome you are mixing styles of awaiting a promise.

    Instead of this:

    const response = await addData("incomes", data).then((res) => {
      const newEntry: IEntry = {
        _id: res.data.income._id,
        user: data.userId,
        label: data.label,
        amount: data.amount,
      };
    
      return newEntry;
    });
    

    Either use this:

    try {
      const response = await addData("incomes", data);
      // do stuff
    } catch (e) {
      console.log(e);
    }
    

    Or do this:

    addData("incomes", data).then((res) => {
      // do stuff
    })
    
    Login or Signup to reply.
  2. I can’t leave a comment (just don’t have enough credit yet).
    You said you checked your store? Are you sure that the data is changed in the store?
    (Because this is async of course, and you’re not managing loading and pending state of your call, probably your UI is rendered before the data is updated.)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search