I have such slice:
import { createSlice, createAsyncThunk } from "#reduxjs/toolkit";
import axios from "axios";
export const fetchNews = createAsyncThunk("blog/fetchNews", async () => {
try {
const { data } = await axios.get(
"https://*my url*"
);
return data;
} catch (error) {
console.log("Error");
}
});
export const blogSlice = createSlice({
name: "blog",
initialState: {
news: [],
status: null,
error: null,
},
reducers: {
setItems(state, action) {
state.news = action.payload;
},
},
extraReducers: {
[fetchNews.pending]: (state) => {
state.status = "loading";
state.status = null;
},
[fetchNews.fulfilled]: (state, action) => {
state.status = "success";
state.news = action.payload;
},
[fetchNews.rejected]: (state, action) => {},
},
});
export const { setMedia } = blogSlice.actions;
export default blogSlice.reducer;
and such store:
import { configureStore } from "#reduxjs/toolkit";
import blog from "./slices/blogSlice";
export const store = configureStore({
reducer: {
blog,
},
});
async function is not called, looking at the trycatch, the function doesn't run at all. I can't figure out what could be wrong. I changed the link to mocapi before posting.
Related
Slice One
/*eslint-disable*/
import { createAsyncThunk, createSlice, PayloadAction } from '#reduxjs/toolkit';
const initialState = { };
const patientSlice = createSlice({
name: 'Patient Slice',
initialState: initialState,
reducers: {
TestingOtherSliceCall: (state: any, { payload }: any) => {
alert('heelllo im from patient slice');
}
},
extraReducers: {
[GetInsurancePayersFilter.pending]: (state: any) => {
state.loadingInsurancePayersFilter = true;
},
[GetInsurancePayersFilter.fulfilled]: (state: any, { payload }: PayloadAction<TPayloadList>) => {
state.loadingInsurancePayersFilter = false;
state.getInsurancePayersFilter = payload;
},
[GetInsurancePayersFilter.rejected]: (state: any) => {
state.loadingInsurancePayersFilter = false;
},
}
});
export const { TestingOtherSliceCall patientSlice.actions;
export const patientReducer = patientSlice.reducer;
Slice Two
/*eslint-disable*/
import { createAsyncThunk, createSlice, PayloadAction } from '#reduxjs/toolkit';
import { TestingOtherSliceCall } from './patient';
const initialState = {};
insurance end ******** */
const userSlice = createSlice({
name: 'User Slice',
initialState: initialState,
reducers: {
DynamicTabAppend: (state: any, { payload }) => {
TestingOtherSliceCall(null);
},
},
extraReducers: {
}
});
export const { TestingOtherSliceCall userSlice.actions;
export const userReducer = userSlice.reducer;
Root Reducer
import { patientReducer } from './../slices/patient';
import { combineReducers } from '#reduxjs/toolkit';
import storage from 'redux-persist/lib/storage';
import { persistReducer } from 'redux-persist';
import { createFilter } from 'redux-persist-transform-filter';
export const rootReducer = combineReducers({
user: userReducer,
patient: patientReducer,
});
export const persistConfig = {
key: 'root',
storage,
whitelist: ['auth', 'schedule'],
};
export const persistedReducer = persistReducer(persistConfig, rootReducer);
I tried calling from one slice reducer to another but function does'nt invoke.
Am trying to make a login and add the return data to state, when I try to update state, it still gets empty state. I have added the code below, Please help me fix it. Am using RTK query to make the login mutation, and am new to this.
My AuthApi.js
import { createApi, fetchBaseQuery } from "#reduxjs/toolkit/query/react";
import { api } from "./api";
export const authApi = createApi({
reducerPath: "authApi",
baseQuery: fetchBaseQuery({
baseUrl: api
}),
endpoints: (builder) => ({
loginUser: builder.mutation({
query: (body) => {
return {
url: "login",
method: "post",
body,
};
},
}),
registerUser: builder.mutation({
query: (body) => {
return {
url: "register",
method: "post",
body,
};
},
}),
}),
});
export const { useLoginUserMutation, useRegisterUserMutation } = authApi;
My userSlice.js
import { createSlice } from "#reduxjs/toolkit";
import { authApi } from "../../services/authApi";
const initialState = {
role: null,
accessToken: null,
userData: null
}
export const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
logout: (state) => {
state.currentUser = null;
state.errorMessage = ''
}
},
extraReducers: (builders) => {
builders.addMatcher(authApi.endpoints.loginUser.matchFulfilled, (state, action) => {
state.userData = action.payload.success.data
state.accessToken = action.payload.success.accessToken
state.role = action.payload.success.roles
})
}
})
export const { logout } = userSlice.actions
export const selectUser = (state) => state.user.accessToken
export default userSlice.reducer
my store.js
import { configureStore } from "#reduxjs/toolkit";
import { authApi } from "../services/authApi";
import userReducer from './slices/userSlice'
const store = configureStore({
reducer: {
[authApi.reducerPath]: authApi.reducer,
user: userReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(authApi.middleware),
});
export default store;
console.log(action.payload) in userSlice extraReducer gives me the data in console, but it is not updating the state.
When retrieving data and console.log it, the data shows perfectly, but when trying to dispatch the action with the argument as a data it turns out to be undefined.
I tried to use await before dispatch the action, but it didn't change anything. Why does it happen?
actions.js
import * as types from './actionTypes'
import { db } from '../firebase';
import { collection, getDocs } from "firebase/firestore";
const getFeedbacksStart = () => ({
type: types.GET_FEEDBACKS_START,
});
const getFeedbacksSussess = (feedbacks) => ({
type: types.GET_FEEDBACKS_SUCCESS,
payload: feedbacks
});
const getFeedbacksFail = () => ({
type: types.GET_FEEDBACKS_FAIL,
});
export const getFeedbacks = () => {
return async function (dispatch) {
dispatch(getFeedbacksStart());
try {
const querySnapshot = await getDocs(collection(db, "feedbacks"));
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data())
});
const feedbacks = querySnapshot.forEach((doc) => doc.data());
dispatch(getFeedbacksSussess(feedbacks))
} catch (error) {
dispatch(getFeedbacksFail(error))
}
}
}
actionTypes.js
export const GET_FEEDBACKS_START = 'GET_FEEDBACKS_START';
export const GET_FEEDBACKS_SUCCESS = 'GET_FEEDBACKS_SUCCESS';
export const GET_FEEDBACKS_FAIL = 'GET_FEEDBACKS_FAIL';
reducer.js
import * as types from './actionTypes'
const initialState = {
feedbacks: {},
loading: false,
error: null,
};
const feedbackReducer = (state = initialState, action) => {
switch (action.type) {
case types.GET_FEEDBACKS_START:
return {
...state,
loading: true
}
case types.GET_FEEDBACKS_SUCCESS:
return {
...state,
loading: false,
feedbacks: action.payload,
}
case types.GET_FEEDBACKS_FAIL:
return {
...state,
loading: false,
error: action.payload,
}
default:
return state;
}
}
export default feedbackReducer;
root-reducer.js
import { combineReducers } from "redux";
import feedbackReducer from "./reducer";
const rootReducer = combineReducers({
data: feedbackReducer,
});
export default rootReducer;
store.js
import { configureStore } from '#reduxjs/toolkit';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import rootReducer from './root-reducer';
const store = configureStore({
reducer: rootReducer,
middleware: [thunk, logger],
});
export default store;
ListRecord.js where I dispatch the action
import React, { useEffect, useState, useContext } from "react";
import { useSelector, useDispatch } from 'react-redux';
import { getFeedbacks } from "../redux/actions";
const ListRecord = () => {
const [data, setData] = useState({});
console.log("data", data);
const state = useSelector(state => state.data);
console.log("state =>", state);
let dispatch = useDispatch();
useEffect(() => {
dispatch(getFeedbacks());
}, [])
return (
<>
</>
);
};
export default ListRecord;
I figured out what I was doing wrong. I tried to retrieve the data in the wrong way. I was trying to use forEach method on a collection. Firstly, it needed to refer to the docs inside a db -> querySnapshot.docs and then you can use .map() method and loop through the whole collection you have inside your database.
The example of how to do it right with firebase v9 is HERE
Here is a working code :)
In actions.js
export const getFeedbacks = () => {
return function (dispatch) {
dispatch(getFeedbacksStart())
const getData = async () => {
try {
const querySnapshot = await getDocs(collection(db, "feedbacks"));
const feedbacks = querySnapshot.docs.map((doc) => ({
...doc.data(),
id: doc.id
}))
dispatch(getFeedbacksSussess(feedbacks));
} catch (error) {
dispatch(getFeedbacksFail(error))
}
}
getData();
}
}
I don't get why dispatch is not sendin list: [] the information, only info I got is list: [] has it's property in never[].
import { createSlice } from "#reduxjs/toolkit";
import axios from "axios";
export const userSlice = createSlice({
name: "users",
initialState: {
list: [] /* (property) list: never[] */
},
reducers: {
setUserList: (state, action) => {
state.list = action.payload;
}
},
});
export const { setUserList } = userSlice.actions;
export default userSlice.reducer;
export const fetchAllUsers = () => (dispatch) => {
axios
.get('https://reqres.in/api/users?page=2')
.then((response) => {
dispatch(setUserList(response.data.data));
})
.catch((error) => console.log(error))
};
I'm trying to use "#reduxjs/toolkit"
So I have a page: "services.reducer.ts":
const initialState = {
entities: [] as ReadonlyArray<IServices>,
entity: defaultValue,
loading: false,
totalItems: 0
}
export type ServiceState = Readonly<typeof initialState>;
export const getEntities = createAsyncThunk(
'services/getEntities',
async () => {
const response = await axios.get<any>(apiUrl)
return response.data
}
)
export const getEntity = createAsyncThunk(
'services/getEntity',
async (id: number | string) => {
const response = await axios.get<any>(`${apiUrl}/${id}`);
return response.data
}
)
export const ServiceSlice = createSlice({
name: 'services',
initialState,
reducers: {},
extraReducers(builder) {
builder
.addCase(getEntities.pending, (state, action) => {
state.loading = false;
})
.addCase(getEntities.fulfilled, (state, action) => {
const { data } = action.payload;
state.entities = data;
state.loading = true;
state.totalItems = parseInt(action.payload.length, 10);
})
.addCase(getEntity.fulfilled, (state, action) => {
const { data } = action.payload;
state.entity = data;
})
}
})
on my services.tsx:
export const Services = (props: IServicesProps) => {
const dispatch = useAppDispatch();
const [list, setList] = useState([]);
const [loading, setLoading] = useState(false)
useEffect(() => {
dispatch(getEntities())
.then((resp) => {
console.log("resp ", resp)
if (resp.payload !== null) {
setLista(resp.payload)
}
})
}, []);
Now my question is: I would to use the info about loading and totalItems for example. But I don't understand how can I use in on my services.tsx
I have, for example, set:
state.loading = true;
state.totalItems = parseInt(action.payload.length, 10);
but I don't understand if they are declared in the right place or not.
EDIT:
store.ts
import { AnyAction, configureStore, ThunkAction } from '#reduxjs/toolkit';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import reducer from 'app/shared/reducers';
import errorMiddleware from './error-middleware';
import notificationMiddleware from './notification-middleware';
import loggerMiddleware from './logger-middleware';
import { loadingBarMiddleware } from 'react-redux-loading-bar';
const store = configureStore({
reducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}).concat(errorMiddleware, notificationMiddleware, loadingBarMiddleware(), loggerMiddleware),
})
const getStore = () => store;
export type IRootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export const useAppSelector: TypedUseSelectorHook<IRootState> = useSelector;
export const useAppDispatch = () => useDispatch<AppDispatch>();
export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, IRootState, unknown, AnyAction>;
export default getStore;
EDIT 2:
import { loadingBarReducer as loadingBar } from 'react-redux-loading-bar';
import { combineReducers } from 'redux';
import authentication, { AuthenticationState } from './authentication';
import applicationProfile, { ApplicationProfileState } from './application-profile';
import administration, { AdministrationState } from 'app/modules/administration/administration.reducer';
import userManagement, { UserManagementState } from './user-management';
// prettier-ignore
import services, {
ServiceState
} from 'app/entities/service/service.reducer';
// prettier-ignore
/* jhipster-needle-add-reducer-import - JHipster will add reducer here */
export interface IRootState {
readonly authentication: AuthenticationState;
readonly applicationProfile: ApplicationProfileState;
readonly administration: AdministrationState;
readonly userManagement: UserManagementState;
readonly services: ServicesState;
readonly loadingBar: any;
}
const rootReducer = combineReducers<IRootState>({
authentication,
applicationProfile,
administration,
userManagement,
services,
,
/* jhipster-needle-add-reducer-combine - JHipster will add reducer here */
loadingBar,
});
export default rootReducer;
EDIT 3: console.log("resp", resp):
{
"type": "services/getEntities/fulfilled",
"payload": [
{
"srvCod": 1,
"srvDescod": "Account Savings",
"srvDescodmaia": "Corporate Islan",
"srvDestitle": "Oklahoma",
},
],
"meta": {
"arg": {
"sortParam": "srvCod,asc",
"pageParam": 0
},
"requestId": "OTD4JuHBUeYF7ueyg6BQ2",
"requestStatus": "fulfilled"
}
}