I am creating a NextJs 14 ecommerce application using redux toolkit for state management. I have created a slice using my best understanding of RTK 2.0 syntax to call user data so that it can be added to my user state.
"use client";
import { buildCreateSlice, asyncThunkCreator } from "@reduxjs/toolkit";
const createSliceWithThunks = buildCreateSlice({
creators: {
asyncThunk: asyncThunkCreator,
},
});
const initialState = {
user: {
_id: "",
fname: "",
lname: "",
email: "",
streetAddress: "",
postalCode: "",
city: "",
county: "",
country: "",
},
loading: false,
error: null,
};
const userSlice = createSliceWithThunks({
name: "user",
initialState,
reducers: (create) => ({
fetchUser: create.asyncThunk(
async (_, thunkApi) => {
const response = await fetch("/api/user");
if (!response.ok) {
throw new Error("Failed to fetch user data");
}
const userData = await response.json();
console.log(userData);
return userData;
},
{
pending: (state) => {
(state.loading = true), (state.error = null);
},
fulfilled: (state, action) => {
state.loading = false;
state.data = action.payload;
},
rejected: (state, action) => {
state.loading = false;
state.error = action.error.message;
},
}
),
}),
});
export const { fetchUser } = userSlice.actions;
export default userSlice.reducer;
This is my api/user route:
import { connectDb } from "@dbConfig/db";
import User from "@models/UserModel";
import { getServerSession } from "next-auth";
import { NextResponse } from "next/server";
export async function GET(req, res) {
const session = getServerSession(); //using my session data from NextAuth to get email to find user in mongodb
try {
const email = (await session).user.email; //I don't know why prettier formatted this line like this, the code breaks if I change it.
connectDb();
const user = await User.findOne({ email });
console.log(user);
return NextResponse.json({ message: "User found:", user }, { status: 201 });
} catch (error) {
console.log(error);
}
}
The call works perfectly, I am getting the user data from my database and can see it when I go to localhost:3000/api/user.
The problem is when I try to get it using Redux-Toolkit and then set my user state to the data received.
When I check the Redux-Devtools in my browser, I can see the data, but it is only appearing under a data
property, and not actually updating state. I am at a loss for how to move forward. Any help is appreciated.
The state is actually updating, you can see the updated state in the dev tool.
However...
There is no data
property in the state until this fetchUser
action is fulfilled, in which case the reducer case sets a state.data
property equal to action.payload
. I suspect you want to be setting the state.user
property to the user
property of the response JSON in the action payload, e.g. state.user = action.payload.user;
.
const initialState = {
user: {
_id: "",
fname: "",
lname: "",
email: "",
streetAddress: "",
postalCode: "",
city: "",
county: "",
country: "",
},
loading: false,
error: null,
};
const userSlice = createSliceWithThunks({
name: "user",
initialState,
reducers: (create) => ({
fetchUser: create.asyncThunk(
async (_, thunkApi) => {
try {
const response = await fetch("/api/user");
const userData = await response.json();
return userData;
} catch(error) {
return thunkApi.rejectWithValue(error);
}
},
{
pending: (state) => {
state.loading = true;
state.error = null;
},
fulfilled: (state, action) => {
state.loading = false;
state.user = action.payload.user; // <-- update user property
},
rejected: (state, action) => {
state.loading = false;
state.error = action.payload.message;
},
}
),
}),
});