Answer the question
In order to leave comments, you need to log in
How to change data from one "duck" to another?
There is a "duck" cart (responsible for the cart). It handles the addition of goods to the cart, and in the state the cart module is stored, which stores the currently added goods to the cart.
There is a "duck" catalog (responsible for the catalog of goods). It processes a request for all products from the database (firebase). The state displays a catalog with all products. Each product has an addedToCart property (whether the product has been added to the cart).
Now it turns out that adding to the cart is processed in one place, and the property needs to be changed in another.
How to change the addedToCart state to true when adding a product? How to change the value in the database is clear, but how to change the state from one duck to another is not clear. Tell me please. Or specify a different logic of work, maybe I didn’t approach the cart correctly at all.
Adding an item to the cart in the "duck" cart:
// ...
case ADD_PRODUCT_TO_CART_SUCCESS: {
return state.setIn(["entities", payload.productUid], new ProductRecord(payload.product));
}
// ...
export const addProductToCartSaga = function * (action) {
const { productUid } = action.payload;
const productRef = firebase.database().ref(`catalog/${productUid}`);
const product = yield call([productRef, productRef.once], "value");
yield put({
type: ADD_PRODUCT_TO_CART_SUCCESS,
payload: {
productUid,
product: product.val()
}
});
};
Answer the question
In order to leave comments, you need to log in
Why does the product have the addedToCart property at all ?
Imagine that you have or will have pagination in your application. You went back and forth and downloaded the products again. The keys will then be lost.
Make selectors checkIsProductAddedToCartSelector and isProductAddedToCartSelector . Let the first one return a function that takes the product id and returns true if the product is found in the basket store . The second one takes the id of the product and returns a boolean value if the product is found or not found in the cart store . Use reselect for this .
And add them tomapStateToProps in connect .
You can call it in a list like this:
const ProductsList = ({
productsList,
checkIsProductAddedToCart,
}) => (
<ul>
{productsList.map(product => (
<Product
addedToCart={checkIsProductAddedToCart(product.id)}
product={product}
/>
))}
</ul>
);
const mapStateToProps(state => ({
productsList: productListSelector(state),
checkIsProductAddedToCart: checkIsProductAddedToCartSelector(state),
}));
export default connect(mapStateToProps)(ProductsList);
const mapStateToProps((state, ownProps) => ({
isAddedToCart: isProductAddedToCartSelector(state, ownProps),
}));
export default connect(mapStateToProps)(ProductDetails);
import { createSelector } from 'reselect';
const cartSelector = state => state.cart;
const cartProductsSelector = createSelector(
cartSelector,
cart => cart.products,
);
// возвращает функцию, принимающую id, которую можно использовать при построении списков
const checkIsProductAddedToCartSelector = createSelector(
cartProductsSelector,
products => id => products.some(product => product.id === id),
);
const productIdSelector = (_, props) => props.product.id;
// возвращает булево значение, важно чтобы в компоненте было свойство product
const isProductAddedToCartSelector = createSelector(
cartProductsSelector,
productIdSelector,
(products, id) => products.some(product => product.id === id),
);
You can change the state of the added product in the catalog reducer using the ADD_PRODUCT_TO_CART_SUCCESS action. Something like:
case ADD_PRODUCT_TO_CART_SUCCESS:
return {
...state,
entities: {
...state.entities,
[action.payload.productUid]: {
...state.entities[action.payload.productUid],
addedToCart: true,
}
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question