Tengo una matriz de objetos de productos dentro de mi reductor y también tengo una matriz vacía de marca. Quiero agregar todas las marcas únicas de mi matriz de objetos de productos a mi matriz de marcas en mi reductor, ¿hay alguna forma de hacerlo?
Mi reductor:
import * as actionTypes from './shop-types'; const INITIAL_STATE = { products: [ { id: 1, brand:"DNMX" }, { id: 2, brand: "Aeropostale", }, { id: 3, brand: "AJIO", }, { id: 4, brand: "Nike", }, ], cart: [], brands: [], //<---- I want to add all the unique brands inside this array currentProduct: null, }; const shopReducer = (state = INITIAL_STATE, action) => { switch (action.type) { case actionTypes.ADD_TO_CART: const product = state.products.find( (product) => product.id === action.payload.id ); if (product !== null) { return { ...state, cart: state.cart.concat(product), }; } else { return null; } default: return state; } }; export default shopReducer;Las marcas son esencialmente datos derivados, lo que significa que se basan o dependen de otros datos. Debido a esto, en realidad no necesita establecerlo en el estado, sino más bien, simplemente derivarlo .
Normalmente recomendaría usar Redux Toolkit ya que es mucho más simple, pero como está usando Redux de la vieja escuela, recomendaría usar una biblioteca llamada Reselect . Es una biblioteca para crear selectores memorizados que puede consumir en su componente.
Para tu ejemplo, intentaría algo como:
// import the createSelector function // we'll use to make a selector import { createSelector } from "reselect" // create a "getter". this is just a simplified // way of accessing state const selectBrands = (state) => state.products // create the selector. this particular selector // just looks at `products` in state (from your // getter), and filters out duplicate values // and returns a unique list const uniqueBrands = createSelector(selectBrands, (items) => items.filter( (item, idx, arr) => arr.findIndex((brand) => brand.name === item.name) === idx ) ) Luego, en el código de su componente, puede acceder a esto en mapStateToProps :
const mapStateToProps = (state) => ({ uniqueBrands: uniqueBrands(state), })Esto no se ha probado actualmente, pero debería ser lo que está buscando.
No está muy claro si te refieres a marcas únicas por carrito o productos, pero no debería cambiar los patrones que usarás para resolver esto.
Primero, suponiendo que la lista de productos no cambie, simplemente puede agregarlos como parte del estado inicial.
const ALL_PRODUCTS = [ { id: 1, brand:"DNMX" }, { id: 2, brand: "Aeropostale" }, { id: 3, brand: "AJIO" }, { id: 4, brand: "Nike" } ]; const distinct = (array) => Array.from(new Set((array) => array.map((x) => x.brand)).entries()); const ALL_BRANDS = distinct(ALL_PRODUCTS.map((x) => x.brand)); const INITIAL_STATE = { products: ALL_PRODUCTS, cart: [], brands: ALL_BRANDS, currentProduct: null, };Si tendrá una acción que agregará nuevos productos y las marcas deben reflejar que solo aplica la lógica anterior durante las actualizaciones de estado de los productos.
const reducer = (state = INITIAL_STATE, action) => { switch(action.type) { case (action.type === "ADD_PRODUCT") { const products = [...state.products, action.product]; return { ...state, products, brands: distinct(products.map((x) => x.brand)) } } } return state; }; Ahora para la manera idiomática. Puede notar que las marcas pueden considerarse derived de la colección de productos. Lo que significa que probablemente ni siquiera lo necesitemos en el estado, ya que podemos usar algo llamado selector para crear valores derivados de nuestro estado, lo que puede simplificar en gran medida nuestra lógica reductora/estructural.
// we dont need brands in here anymore, we can derive. const INITIAL_STATE = { products: ALL_PRODUCTS, cart: [], currentProduct: null; }; const selectAllBrands = (state) => { return distinct(state.products.map((x) => x.brand)) };Ahora, cuando agregamos/eliminamos/editamos nuevos productos, ya no necesitamos actualizar la porción de la marca. Se derivará del estado actual de los productos. Además de todo eso, puede componer selectores tal como lo hace con reductores para obtener una lógica realmente compleja sin estropear su tienda.
const selectCart = (state) => state.cart; const selectAllBrands = (state) => {...see above} const selectTopBrandInCart = (state) => { const cart = selectCart(state); const brands = selectBrands(brands); // find most popular brand in cart and return it. };Le recomiendo encarecidamente que consulte reseleccionar para ayudar a crear selectores componibles y de alto rendimiento.