Slice
import { createSlice } from '#reduxjs/toolkit';
const initialState: { value: number } = { value: 0 };
export const testSlice = createSlice({
name: 'test',
initialState,
reducers: {
test: (state) => {
state.value += 1;
},
},
});
export const { test } = testSlice.actions;
Combine
import { combineReducers } from '#reduxjs/toolkit';
import { authSlice } from './auth';
import { productsSlice } from './products';
import { testSlice } from './test';
import { userSlice } from './user';
export const rootReducer = combineReducers({
user: userSlice.reducer,
auth: authSlice.reducer,
products: productsSlice.reducer,
test: testSlice.reducer,
});
export type RootState = ReturnType<typeof rootReducer>;
Store
import { configureStore } from '#reduxjs/toolkit';
import storage from 'utils/storage';
import { rootReducer } from './rootReducer';
declare global {
interface Window {
store: any;
}
}
const reHydrateStore = () => {
if (storage.getToken() !== null) {
return storage.getToken();
}
return false;
};
// !TODO add types
// #ts-ignore
const localStorageMiddleware = (store) => (next) => (action) => {
if (action.type.match('auth')) {
const result = next(action);
storage.setToken(store.getState().auth.token);
return result;
}
return next(action);
};
export const store = configureStore({
reducer: rootReducer,
preloadedState: {
auth: {
token: reHydrateStore() || '',
loading: false,
},
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(localStorageMiddleware),
});
window.store = store.getState();
When I output store.test to the console, the value remains old, but auth reducer works correctly.
Also I see that the state after the update in the reducers is 0.
Why is state not being updated?
Above are examples of my code:
Сreate Slice
Combine reducers
Store settings (and output store in console)
Related
Auth.js
import { createSlice } from "#reduxjs/toolkit";
export const authSlice = createSlice({
name: "auth",
initialState: {
isAuthenticated: false,
user: {},
},
reducers: {
setUser: (state, { payload }) => {
state.user = payload.user;
state.isAuthenticated = true;
},
logout: (state) => {
state.user = {};
state.isAuthenticated = false;
},
},
});
export const { setUser, logout } = authSlice.actions;
export default authSlice.reducer;
index.js (store)
import { configureStore } from "#reduxjs/toolkit";
import authReducer from "./auth.js";
export default configureStore({
reducer: {
auth: authReducer,
},
});
transaction form.js
const { categories } = useSelector((state) => state.auth.user);
** when I logged in there was a error but on reloading the page the error is gone. How to fix the error**
If you are not logged in, you don't get a user, and then you cannot extract categories from it. Several solutions, one is
const { categories } = useSelector((state) => state.auth.user ?? {categories: []});
Depending on what you do with the user and category data, you might be better off doing something like this:
const user = useSelector((state) => state.auth.user);
if(!user){
return;
}
const categories = user.categories
...
here is my redux store code it gives the input type error or input invalid error
but this error is coming in development mode not on production why it is so, i don't have any clue
import { createStore, applyMiddleware, combineReducers } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import sessionStorage from "redux-persist/lib/storage/session";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
import { createStateSyncMiddleware } from "redux-state-sync";
const SET_CLIENT_STATE = "SET_CLIENT_STATE";
const middlewares = [
thunk,
createStateSyncMiddleware({
// blacklist: ["extras", "products"]
whitelist: ["user"],
}),
];
const persistConfig = {
key: "root",
storage,
whitelist: ["user", "loggedInDoctor", "loggedInPatient"],
};
const sessionRedConfig = {
key: "referrer",
storage: sessionStorage,
};
const { referrer, ...otherReducer } = rootReducer;
const allReducers = combineReducers({
...otherReducer,
referrer: persistReducer(sessionRedConfig, referrer),
});
const persistedReducer = persistReducer(persistConfig, allReducers);
const makeConfiguredStore = (reducer, initialState) =>
createStore(
reducer,
initialState,
composeWithDevTools(applyMiddleware(...middlewares))
);
export const makeStore = (initialState, { isServer, req, debug, storeKey }) => {
if (isServer) {
initialState = initialState || { fromServer: "foo" };
return makeConfiguredStore(allReducers, initialState);
} else {
// we need it only on client side
const store = makeConfiguredStore(persistedReducer, initialState);
store.__persistor = persistStore(store); // Nasty hack
return {
...store,
store,
};
}
};
export const setClientState = (clientState) => ({
type: SET_CLIENT_STATE,
payload: clientState,
});
I'm new in Redux and I've got some issues learning it.
If I call a selector before a dispatch it becomes in an infinite loop, but if I call the selector after the dispatch action it works fine. I've followed documentations steps and look through stack-overflow and couldn't find some issue similar.
I let the code below:
selector:
import { createSelector } from '#reduxjs/toolkit';
import { RootState } from '#/store';
export const selectCount = (state: RootState) => state.learningLanguages;
export const countSelector = createSelector(selectCount, state => state);
action:
import {createAction} from "#reduxjs/toolkit"
import {LearningLanguagesType} from "#/globals";
export const storeLearningLanguages = createAction<LearningLanguagesType[]>('languages/store')
reducer
import {
createReducer, createSlice, PayloadAction,
} from '#reduxjs/toolkit';
import { LearningLanguagesType } from "#/globals";
import {storeLearningLanguages} from "#/store";
const initialState: LearningLanguagesType[] = [{
id: 'en',
name: 'english',
level: '0'
}];
export const learningLanguagesReducer = createReducer(initialState, builder => {
builder
.addCase(storeLearningLanguages, (state, action) => {
return action.payload;
});
});
hooks
import {
TypedUseSelectorHook,
useDispatch,
useSelector,
} from 'react-redux';
import type {
AppDispatch,
RootState,
} from '.';
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
store
import {
Action,
configureStore,
ThunkAction,
} from '#reduxjs/toolkit';
import {learningLanguagesReducer} from './app/languages/reducer'
export const index = configureStore({
reducer: {
learningLanguages : learningLanguagesReducer
},
});
export type AppDispatch = typeof index.dispatch;
export type RootState = ReturnType<typeof index.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;
execution
import {
useAppDispatch,
useAppSelector,
} from '#/store/hooks'
import {LearningLanguagesType} from "#/globals";
const Home = () => {
const dispatch = useAppDispatch();
const testLang: LearningLanguagesType[] = [
{
id: 'es',
name: 'Spain',
level: '0'
},
{
id: 'en',
name: 'English',
level: '0'
}
];
console.log('before',useAppSelector(countSelector))
console.log('dispatch', (dispatch(storeLearningLanguages(testLang))))
console.log('after',useAppSelector(countSelector))
}
This way works perfectly, and it doesn't matter how many times I call the selector after the dispatch:
//console.log('before',useAppSelector(countSelector))
console.log('dispatch', (dispatch(storeLearningLanguages(testLang))))
console.log('after',useAppSelector(countSelector))
Thanks anyway.
I'm using React and Redux for creating a shop website. I want to add items to the cart using redux, but cart items it's not getting added only showing an error:
GET http://localhost:3000/api/v1/product/61db003374fe4392e3446ae3 404 (Not Found)
"Uncaught (in promise) Error: Request failed with status code 404"
and I suppose the problem is maybe with ID in action but I'm not sure how to fix it.
Please help me out. Below is my code
// reducer
import { ADD_TO_CART } from '../constants/cartConstants';
export const cartReducer = (state = { cartItems: [] }, action) => {
switch (action.type) {
case ADD_TO_CART:
const item = action.payload;
const isItemExist = state.cartItems.find(
(i) => i.product === item.product
);
if (isItemExist) {
return {
...state,
cartItems: state.cartItems.map((i) =>
i.product === isItemExist.product ? item : i
),
};
} else {
return {
...state,
cartItems: [...state.cartItems, item],
};
}
default:
return state;
}
};
// actions
import axios from 'axios';
import { ADD_TO_CART } from '../constants/cartConstants';
export const addItemToCart = (id, quantity) => async (dispatch, getState) => {
const { data } = await axios.get(`/api/v1/product/${id}`);
dispatch({
type: ADD_TO_CART,
payload: {
product: data.product._id,
name: data.product.name,
price: data.product.price,
image: data.product.images[0].url,
stock: data.product.stock,
quantity,
},
});
localStorage.setItem('cartItems', JSON.stringify(getState().cart.cartItems));
};
// store
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import {
productsReducer,
productsDetailsReducer,
} from './reducers/productReducers';
import {
authReducer,
userReducer,
forgotPasswordReducer,
} from './reducers/userReducers';
import { cartReducer } from './reducers/cartReducers';
const reducer = combineReducers({
products: productsReducer,
productDetails: productsDetailsReducer,
auth: authReducer,
user: userReducer,
forgotPassword: forgotPasswordReducer,
cart: cartReducer,
});
let initialState = {
cart: {
cartItems: localStorage.getItem('cartItems')
? JSON.parse(localStorage.getItem('cartItems'))
: [],
},
};
const middleware = [thunk];
const store = createStore(
reducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
I've looked on other posts and it seemed to be a naming export thing, but I looked over and over my code and can't figure it out. I will appreciate any advice.
this is the error I'm getting:
TypeError: (0 , _redux_wetherSlice__WEBPACK_IMPORTED_MODULE_2__.setLocalLatitude) is not a function
at localWether.js:14
slice component
import { createSlice } from "#reduxjs/toolkit";
export const wetherSlice = createSlice({
name: "wether",
initialState: {
localLocation: {
latitude: "",
longitude: "",
},
reducers: {
setLocalLatitude: (state, action) => {
state.localLocation.latitude = action.payload;
},
setLocalLongitude: (state, action) => {
state.localLocation.longitude = action.payload;
},
},
},
});
export const { setLocalLongitude, setLocalLatitude } = wetherSlice.actions;
export default wetherSlice.reducer;
react component
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { setLocalLatitude, setLocalLongitude } from "../../redux/wetherSlice";
const LocalWether = () => {
const dispatch = useDispatch();
const { localLocation } = useSelector((state) => state.wether);
useEffect(() => {
navigator.geolocation.getCurrentPosition((position) => {
try {
console.log(position);
dispatch(setLocalLatitude(position.coords.latitude));
dispatch(setLocalLongitude(position.coords.longitude));
} catch (err) {
console.log(err);
}
});
}, []);
console.log(localLocation);
return <button>Click For Location</button>;
};
export default LocalWether;
store
import { configureStore } from "#reduxjs/toolkit";
import wetherReducer from "../redux/wetherSlice";
const store = configureStore({
reducer: { wether: wetherReducer },
});
export default store;