Why filter method in my reducer returns an array of proxy? -Redux Toolkit - redux

so i want to delete an item from array, onClick but when i log the filtered data in the console i get an array of Proxy.
i tried Changing my code but nothing worked
whats wrong here in itemRemoved?
import { createSlice, createAction } from "#reduxjs/toolkit";
// Action Creater
const slice = createSlice({
name: "shoppingCart",
initialState: [],
reducers: {
itemAdded: some code // ,
itemRemoved: (cart, { payload }) => {
cart.filter((item) => {
if (item.id === payload.id) {
if (item.count === 1) {
return cart.filter((item) => item.id !== payload.id);
}
else {
const itemIndex = cart.indexOf(item);
cart[itemIndex].count = cart[itemIndex].count - 1;
return cart;
}
}
});
},
},
});
export const { itemAdded, itemRemoved } = slice.actions;
export default slice.reducer;

Assuming you want to remove the element with the id you are passing through the dispatch function
itemRemoved: (state, { payload }) => {
const newCart = state.cart.filter(item => item.id !== payload.id)
const state.cart = newCart
return state
}),

Related

I cannot understand WHY I cannot change state in Redux slice

I get the array of objects coming from backend, I get it with socket.io-client. Here we go!
//App.js
import Tickers from "./Components/TickersBoard";
import { actions as tickerActions } from "./slices/tickersSlice.js";
const socket = io.connect("http://localhost:4000");
function App() {
const dispatch = useDispatch();
useEffect(() => {
socket.on("connect", () => {
socket.emit("start");
socket.on("ticker", (quotes) => {
dispatch(tickerActions.setTickers(quotes));
});
});
}, [dispatch]);
After dispatching this array goes to Action called setTickers in the slice.
//slice.js
const tickersAdapter = createEntityAdapter();
const initialState = tickersAdapter.getInitialState();
const tickersSlice = createSlice({
name: "tickers",
initialState,
reducers: {
setTickers(state, { payload }) {
payload.forEach((ticker) => {
const tickerName = ticker.ticker;
const {
price,
exchange,
change,
change_percent,
dividend,
yeild,
last_trade_time,
} = ticker;
state.ids.push(tickerName);
const setStatus = () => {
if (ticker.yeild > state.entities[tickerName].yeild) {
return "rising";
} else if (ticker.yeild < state.entities[tickerName].yeild) {
return "falling";
} else return "noChange";
};
state.entities[tickerName] = {
status: setStatus(),
price,
exchange,
change,
change_percent,
dividend,
yeild,
last_trade_time,
};
return state;
});
return state;
},
},
});
But the state doesn't change. I tried to log state at the beginning, it's empty. After that I tried to log payload - it's ok, information is coming to action. I tried even to do so:
setTickers(state, { payload }) {
state = "debag";
console.log(state);
and I get such a stack of logs in console:
debug
debug
debug
3 debug
2 debug
and so on.

How to call a function from another component

I am using Alan AI voice assistant, so I am trying to trigger a function from another component based on the voice command.
This is the component holding the function I want to call
const CartButton: React.FC<CartButtonProps> = ({
className,
isShowing,
}) => {
const { openDrawer, setDrawerView } = useUI();
function handleCartOpen() {
setDrawerView('CART_SIDEBAR');
isShowing;
return openDrawer();
}
return (
<button
className={cn(
'flex items-center justify-center',
className
)}
onClick={handleCartOpen}
aria-label="cart-button"
>
</button>
);
};
export default CartButton;
So in the component above I want to use the handleCartOpen function in the below component
const COMMANDS = {
OPEN_CART: "open-cart",
}
export default function useAlan() {
const [alanInstance, setAlanInstance] = useState()
const openCart = useCallback(() => {
alanInstance.playText("Opening cart")
// I want to call the handleCartOpen function here
}, [alanInstance])
useEffect(() => {
window.addEventListener(COMMANDS.OPEN_CART, openCart)
return () => {
window.removeEventListener(COMMANDS.OPEN_CART, openCart)
}
}, [openCart])
useEffect(() => {
if (alanInstance != null) return
const alanBtn = require('#alan-ai/alan-sdk-web');
setAlanInstance(
alanBtn({
key: process.env.NEXT_PUBLIC_ALAN_KEY,
rootEl: document.getElementById("alan-btn"),
onCommand: ({ command, payload }) => {
window.dispatchEvent(new CustomEvent(command, { detail: payload }))
}
}));
}, []);
}
So in the openCart Callback, i want to trigger the handleCartOpen function which is in the first component

Redux state doesn't update immediately

I have super simple question
Why my redux state doesn't update immediately?
const { reducer, actions } = createSlice({
name: "professionals",
initialState: {
loading: false,
lastFetchList: undefined,
list: undefined,
professional: undefined,
filters: {
virtual: false
}
},
reducers: {
professionalsListRequested: (professionals, action) => {
if (action.payload.withLoading) professionals.loading = true;
},
professionalsListRequestFailed: (professionals, action) => {
professionals.loading = false;
},
professionalsListReceived: (professionals, action) => {
professionals.lastFetchList = Date.now();
professionals.list = action.payload.data.dataArr;
professionals.loading = false;
},
virtualUpdated: (categories, action) => {
categories.filters.virtual = action.payload;
}
},
});
export const { virtualUpdated } = actions;
export default reducer;
it is my slice.
and here is code of the component :
const dispatch = useDispatch();
const filters = useSelector((state) => state.professionals.filters);
const handlePressOnVirtual = async () => {
console.log("Before" , filters.virtual)
await dispatch(virtualUpdated(!filters.virtual));
console.log("after" , filters.virtual)
};
when handlePressOnVirtual function is called the both console.log(s) print previous value of the state.
When you are still in handlePressOnVirtual function, you are still in a closure, so all the references will still be your existing filters
So you would need to wait for another re-render for useSelector to invoke again then the new values will come.
One way to see the latest changes is to put your log inside a useEffect:
useEffect(() => {
console.log("after" , filters.virtual)
},[filters.virtual]);

useEffect infinite loop with dependency array on redux dispatch

Running into an infinite loop when I try to dispatch an action which grabs all recent posts from state.
I have tried the following in useEffect dependency array
Object.values(statePosts)
useDeepCompare(statePosts)
passing dispatch
omitting dispatch
omitting statePosts
passing statePosts
doing the same thing in useCallback
a lot of the suggestions came from here
I have verified that data correctly updates in my redux store.
I have no idea why this is still happening
my component
const dispatch = useDispatch()
const { user } = useSelector((state) => state.user)
const { logs: statePosts } = useSelector((state) => state.actionPosts)
const useDeepCompare = (value) => {
const ref = useRef()
if (!_.isEqual(ref.current, value)) {
ref.current = value
}
return ref.current
}
useEffect(() => {
dispatch(getActionLogsRest(user.email))
}, [user, dispatch, useDeepCompare(stateLogs)])
actionPosts createSlice
const slice = createSlice({
name: 'actionPosts',
initialState: {
posts: [],
},
reducers: {
postsLoading: (state, { payload }) => {
if (state.loading === 'idle') {
state.loading = 'pending'
}
},
postsReceived: (state, { payload }) => {
state.posts = payload
},
},
})
export default slice.reducer
const { postsReceived, postsLoading } = slice.actions
export const getActionPostsRest = (email) => async (dispatch) => {
try {
dispatch(postsLoading())
const { data } = await getUserActionPostsByUser({ email })
dispatch(postsReceived(data.userActionPostsByUser))
return data.userActionPostsByUser
} catch (error) {
throw new Error(error.message)
}
}
Remove dispatch from dependencies.
useEffect(() => {
dispatch(getActionLogsRest(user.email))
}, [user, dispatch, useDeepCompare(stateLogs)])
you cannot use hook as dependency and by the way, ref.current, is always undefined here
const useDeepCompare = (value) => {
const ref = useRef()
if (!_.isEqual(ref.current, value)) {
ref.current = value
}
return ref.current
}
because useDeepCompare essentially is just a function that you initiate (together with ref) on each call, all it does is just returns value. That's where the loop starts.

update value of an element of object array in redux store

There is a challenge update existing elements value in json array in redux store by an action creater.
You can run code here also shared it below;
console.clear()
const CreateTeam = (team, point) => {
return {
type:"CREATE_TEAM",
payload: {team, point}
}
}
const UpdateTeam = (team, point) => {
return {
type:"UPDATE_TEAM_POINT",
payload: {team, point}
}
}
const TeamReducer = (state = [], action) => {
if(action.type == "CREATE_TEAM")
{
return [...state, action.payload]
}
if(action.type == "UPDATE_TEAM_POINT")
{
let point=action.payload.point;
return [...state, {
...state.teams,
point:point
}]
}
return state;
}
const { createStore, combineReducers } = Redux;
const league = combineReducers({
teams: TeamReducer
})
const store = createStore(league);
store.dispatch(CreateTeam("TeamA",10));
store.dispatch(CreateTeam("TeamB",20));
store.dispatch(UpdateTeam("TeamA",15));//not work
console.log(store.getState())
create actions works fine, I expected the point value of TeamA set to 15.. but its added new object has only "point" property value 15
There is an error in name of actionTypes:
action dispatches type:"UPDATE_TEAM"
reducer handles action.type == "UPDATE_TEAM_POINT"
You have to perform immutable change, try this:
const TeamReducer = (state = [], action) => {
if(action.type == "CREATE_TEAM")
{
return [...state, action.payload]
}
if(action.type == "UPDATE_TEAM")
{
const {team, point} = action.payload;
const changedIdx = state.findIndex((item) => item.team === team);
return [...state.slice(0, changedIdx), action.payload, ...state.slice(changedIdx + 1)]
}
return state;
}

Resources