I created a redux store with 2 different "Slice". First, I have an appSlice:
appSlice.ts
import { createSlice, PayloadAction } from "#reduxjs/toolkit";
import type { RootState } from "./store";
export interface CounterState {
value: number;
}
const initialState: CounterState = {
value: 0,
};
export const appSlice = createSlice({
name: "counter",
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload;
},
},
});
export const { increment, decrement, incrementByAmount } = appSlice.actions;
export const selectCount = (state: RootState) => state.app.value;
export default appSlice.reducer;
And I have a cameraSlice.ts
import { createSlice, PayloadAction } from "#reduxjs/toolkit";
import type { RootState } from "./store";
export interface CameraState {
cameraImage: string | null;
}
const initialState: CameraState = {
cameraImage: null,
};
export const cameraSlice = createSlice({
name: "camera",
initialState,
reducers: {
setCameraImage: (state, action: PayloadAction<string>) => {
state.cameraImage = action.payload;
},
resetCameraImage: (state) =>{
state.cameraImage=null;
}
},
});
export const { setCameraImage, resetCameraImage } = cameraSlice.actions;
export const selectCameraImage = (state: RootState) => state.camera.cameraImage;
export default cameraSlice.reducer;
The error coming from this selectCameraImage, the error message: Property 'cameraImage' does not exist on type 'CounterState'.
Now my store looks like this:
store.ts
import { configureStore } from "#reduxjs/toolkit";
import appReducer from "./appSlice";
import cameraReducer from "./appSlice";
export const store = configureStore({
reducer: {
app: appReducer,
camera: cameraReducer,
},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
hooks.ts:
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import type { RootState, AppDispatch } from "./store";
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
How can I fix that issue? Now, the app and the camera are CounterState type, I don't know why.
If you have any idea, please let me know! Thanks for your time!
I don't see a CounterState defined anywhere there, so maybe you just have another file flying around?
Also, if you take a look at your imports,
import appReducer from "./appSlice";
import cameraReducer from "./appSlice";
is definitely wrong.
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.
I trying to connect my redux store in to my component, but typescript complains that something is wrong. I thoni, someshing wrong with my path or with props
Component
import { FC } from "react";
import Header from "./header/Header";
import PokemonsList from "./pokemonList/PokemonsList";
import PokemonCard from "./pokemonCard/PokemonCard";
import {connect} from 'react-redux';
import { IPokemonsState } from "../types/interfaces";
import { AppStateType } from "../store";
type Props = {
pokemons: Array<any>
}
const Pokemons: FC<Props> = ({pokemons}) => {
return (
<div className="app">
<Header />
<PokemonsList />
<PokemonCard />
</div>
);
};
const mapStateToProps = (state: AppStateType)=>({
pokemons: state.pokemons.pokemonsList
})
export default connect<IPokemonsState>(mapStateToProps)(Pokemons);
interfaces
export interface IAction {
type: string;
payload: {
pokemonsData: Array<any>;
};
}
export interface IPokemonsState {
pokemonsList: Array<any>;
}
export type TPokemons = Array<any>;
export type DispatchType = (args: IAction) => IAction;
store
import pokemonsReducer from "./features/pokemons.reducer";
import { createStore, applyMiddleware, compose, combineReducers } from "redux";
import thunk from "redux-thunk";
declare global {
interface Window {
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose;
}
}
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const reducer = combineReducers({
pokemons: pokemonsReducer,
});
type RootReducerType = typeof reducer;
export type AppStateType = ReturnType<RootReducerType>;
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)));
export default store;
reducer
import { IAction, IPokemonsState } from "../types/interfaces";
import { POKEMONS_DATA } from "./pokemons.actions";
const initialState: IPokemonsState = {
pokemonsList: [1, 2, 3],
};
const pokemonsReducer = (
state: IPokemonsState = initialState,
action: IAction
IPokemonsState => {
switch (action.type) {
default:
return state;
}
};
export default pokemonsReducer;
Please, help me. I think something wrong with types, but actually i don't have any ideas.
So I'm having a problem wherein my reducer is undefined and I don't freaking understand what it means. It's working when it is not array but when array it is not working.
My code should be like this.
In my groupSlice.ts it is something like this
export interface GroupState {
grouplist: (string)[];
}
const groupInitialState: GroupState = {
grouplist:['Binary','Jhonny Sins']
}
export const createGroup = createSlice({
name: 'group',
initialState:groupInitialState,
reducers:{
addGroup: (state,action) => {
state.grouplist.push(action.payload)
},
subGroup: ( state,action ) => {
state.grouplist.filter((group) => group != action.payload)
}
}
})
...
And then I store it here at my store.ts
import { configureStore, ThunkAction, Action } from '#reduxjs/toolkit';
import { createGroup } from '../features/counter/groupSlice';
export const store = configureStore({
reducer: {
groupings: createGroup.reducer,
},
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;
And then the hook.ts to pass on my state in reducer.
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
but when I pass it here in my Group.tsx it says my grouplist is undefined even I already input a an array at string[]
import React,{ useState,useEffect } from 'react'
import styles from './Group.module.css'
import {
addGroup,
subGroup
} from './groupSlice';
import { useAppSelector, useAppDispatch } from '../../app/hooks';
import { RootState } from '../../app/store';
// HERE IS MY ERROR THAT DOESN"T WORK>
export const selectCount = (state: RootState) => {
console.log(state.groupings?.grouplist)
const groupList = state.groupings?.grouplist
return groupList;
}
const Grouping = () => {
const groups = useAppSelector(selectCount);
const dispatch = useAppDispatch();
const [groupName, setGroupName] = useState('');
return (
...
)
}
export default Grouping
So I'm trying to say that my grouplist is undefined but I don't know why since I already input a list values there. Can anyone spotted the mistake here? Thanks.
In the subGroup reducer:
state.grouplist.filter(...)
This only returns the filtered array, it doesn't change it in place (unlike push), so you need to reassign it:
state.grouplist = state.grouplist.filter(...)
import { createSlice } from '#reduxjs/toolkit';
export const userSlice = createSlice({
name: 'user',
initialState: {
user: null,
},
// The `reducers` field lets us define reducers and generate associated actions
reducers: {
login: (state, action) => {
state.user = action.payload;
},
logout: (state) => {
state.user = null;
},
},
});
export const { login, logout } = userSlice.actions;
export const selectUser = (state) => state.user.user;
export default userSlice.reducer;
Error: userSlice.js:22 Uncaught TypeError: Cannot read properties of
undefined (reading 'user')
at selectUser (userSlice.js:22:1)
export const selectUser = (state) => state.user === null ? '' : state.user.user;
// or
export const selectUser = (state) => state.user === null ? {} : state.user.user;
you need to use configureStore and use useSelector to get the user
step1:
you can create new file named store or any name you want
import { configureStore } from "#reduxjs/toolkit";
import User from "./slices/userSlice";
const store = configureStore({
reducer: {
User: User,
},
});
export default store;
step2:
you need to add the provider in the index.js like this:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store/index";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
step3:
use useSelector to get the user from any place like this :
const user = useSelector((state) => state.User.user);
console.log(user);
Try declaring the initial state outside the createSlice function
import { createSlice } from '#reduxjs/toolkit';
const initialState = { user: null }
export const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
login: (state, action) => {
state.user = action.payload;
},
logout: (state) => {
state.user = null;
},
},
});
export const { login, logout } = userSlice.actions;
export const selectUser = (state) => state.user.user;
export default userSlice.reducer;
Or simple just put an object in the place of initialState,
so something like
import { createSlice } from '#reduxjs/toolkit';
const initialState = { user: null }
export const userSlice = createSlice({
name: 'user',
//you put your initialState object here
{user : null},
reducers: {
login: (state, action) => {
state.user = action.payload;
},
logout: (state) => {
state.user = null;
},
},
});
export const { login, logout } = userSlice.actions;
export const selectUser = (state) => state.user.user;
export default userSlice.reducer;
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"
}
}