I'm trying to migrate an existing but old project to newer technologies, and specifically those mentioned in the title. I have little experience with Typescript, none with redux-toolkit and I'm used to Firebase v8 but migrating to v9 for modularity.
So, in my firebase realtime database I have a users table that I want to fetch some informations from, and I'm trying to achieve this through createAsyncThunk
from @reduxjs/toolkit
but with bad luck to this point. Standard actions are processed the way they're supposed to so it's definitely the thunk thing creating problems. I'm attaching some code:
The thunk
import { createAsyncThunk } from "@reduxjs/toolkit";
import { ref, onValue, DataSnapshot, child, DatabaseReference } from "firebase/database";
import { usersDb } from '../Firebase/utils';
import { MyBrandAppUser } from "../Types/MyBrandAppUser";
export const fetchMyBrandAppUser = createAsyncThunk('users/fetchMyBrandAppUser', async (uid: string, thunkAPI) => {
const userEntry: DatabaseReference = child(usersDb, uid);
let theUser: MyBrandAppUser | null = null;
await onValue(userEntry, (snapshot: DataSnapshot) => {
if( snapshot.exists() )
theUser = <MyBrandAppUser>snapshot.val();
else
return null;
},
(err: Error) => {
thunkAPI.rejectWithValue(err)
});
return theUser;
})
I'm afraid this first part won't achieve what I assume it should since that onValue
won't return a promise, but that's another topic for another time maybe.
The store
import { configureStore, EnhancedStore } from "@reduxjs/toolkit";
import userReducer from '../Features/Auth';
import logger from "redux-logger";
import thunk from "redux-thunk";
import { useDispatch } from 'react-redux'
export const store: EnhancedStore = configureStore({
reducer: {
auth: userReducer,
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
serializableCheck: false,
}).concat(logger).concat(thunk)
})
export type AppDispatch = typeof store.dispatch;
export const useAppDispatch = () => useDispatch<AppDispatch>();
My users slice:
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { User } from "firebase/auth";
import { WritableDraft } from "immer/dist/internal";
import { UserState } from "../../Types/Redux/States";
import { fetchMyBrandAppUser } from "../../API/fetchUser";
import { MyBrandAppUser } from "../../Types/MyBrandAppUser";
const initialState: UserState = {
firebaseUser: undefined,
myBrandAppUser: undefined,
}
const authSlice = createSlice({
name: "users",
initialState,
reducers: {
setFirebaseUser: (state: WritableDraft<UserState>, action:PayloadAction<User | null>) => {
state.firebaseUser = action.payload;
},
},
extraReducers: builder => {
builder.addCase(fetchMyBrandAppUser.fulfilled, (state: WritableDraft<UserState>, action) => {
state.myBrandAppUser = action.payload;
})
}
})
export const { setFirebaseUser } = authSlice.actions;
export default authSlice.reducer;
But now if I try to call dispatch(fetchMyBrandAppUser(userID))
typescript won't let me, with the following complaint:
Argument of type '{ payload: User | null; type: string; }' is not assignable to parameter of type 'never'.ts(2345)
Argument of type 'AsyncThunkAction<null, string, {}>' is not assignable to parameter of type 'never'.ts(2345)
What am I doing wrong?
I solved the issue by removing the EnhancedStore
type on the store, for future reference.