Originally, Redux reducer functions is pure, side-effect free, synchronous.
Then Where should side-effects and async tasks be executed?
1. Inside the components (e.g useEffect hook)
2. Inside the action creaters
Frontend code depends on Backend code. If Backend does a lot of work, Frontend just send and recive data, use response data. However, If backend has lean functions, Frontend transform data and send data.
We don't have any backend function right now, so let's guess that frontend should do more works.
const updatedItems = cart.items.slice()
<- this will create new object which is not related to redux state.Actually Writing this kind of code in component needs duplication or external function module when you need it in other places.
Also, This is not goal of using redux. If you transform data in component, redux just handling state change, not complex actions.
Therefore, you can consider write this logic differently.
let isInitial = true;
function App() {
const dispatch = useDispatch();
const showCart = useSelector((state) => state.ui.cartIsVisible);
const cart = useSelector((state) => state.cart);
useEffect(() => {
const sendData = async () => {
const response = await fetch(
"https://react-http-975ab-default-rtdb.firebaseio.com/cart.json",
{
method: "PUT",
body: JSON.stringify(cart),
}
);
if (!response.ok) {
throw new Error("Failed!");
}
};
if (isInitial) {
isInitial = false;
return;
}
});
}, [cart, dispatch]);
return (
// something
);
}
In App.js (It doesn't need to be app.js), I'm using useEffect() to send http request. This is exactly what we wanted .
With dependencies 'cart', whenever cart updated, our http request function will send request to backend.
The reason i set 'isInitial' is to prevent initial execution because useEffect will be executed when app executed.
export const cartActions = cartSlice.actions;
When you use redux toolkit, The good this is there is built-in transformation of actions.
Event though we set function in redux store , we can use that in dispatch function as an action because it returns a function which returns the action
export const sendCartData = (cart) => {
return async (dispatch) => {
dispatch(
uiActions.showNotification({
status: "pending",
title: "Sending...",
message: "Sending cart data",
})
);
try {
const response = await fetch(
"https://react-http-975ab-default-rtdb.firebaseio.com/cart.json",
{
method: "PUT",
body: JSON.stringify(cart),
}
);
if (!response.ok) {
throw new Error("Failed");
}
dispatch(
uiActions.showNotification({
status: "success",
title: "Success!",
message: "Sent cart data successfully",
})
);
} catch (error) {
dispatch(
uiActions.showNotification({
status: "error",
title: "Error!",
message: "Sending cart data failed",
})
);
}
};
};
useEffect(() => {
if (isInitial) {
isInitial = false;
return;
}
dispatch(sendCartData(cart));
}, [cart, dispatch]);
Find Chrome extension