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
Inside
addUserIncome
you are mixing styles of awaiting a promise.Instead of this:
Either use this:
Or do this:
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.)