TypeError: Cannot destructure property 'title' of 'collections' as it is undefined - reactjs

I am trying to get collections using selectors. Here is my code:
Selectors
import { createSelector } from "reselect";
export const selectShop = state => state.shop;
export const selectCollections = createSelector(
[selectShop],
shop => shop.collections
)
export const selectCollectionForPreview = createSelector(
[selectCollections],
collections => Object.keys(collections).map(key => collections[key])
)
export const selectCollectionItem = collectionUrl =>
createSelector(
[selectCollections],
collections => collections[collectionUrl]
//It seems that the selector above is returning collections as an array instead of object, so collections[collectionUrl] is returning undefined
)
Component
const CollectionPage = ({collections}) => {
// const {title, items} = Object.keys(collections)
const {title, items} = collections
console.log('collection', collections);
return(
// <></>
<div className="collection-page">
<h2 className='title'>{title}</h2>
<div className='items'>
{items.map( item =>
<CollectionItem key={item.id} item={item}/>
)}
</div>
</div>
)
}
const mapStateToProps = (state,ownProps) => ({
collections: selectCollectionItem(ownProps.match.params.collectionId)(state)
})
export default connect(mapStateToProps)(CollectionPage);
SHOP_DATA
const SHOP_DATA = {
hats:{
id: 1,
title: 'Hats',
routeName: 'hats',
items: [
{
id: 1,
name: 'Brown Brim',
imageUrl: 'https://i.ibb.co/ZYW3VTp/brown-brim.png',
price: 25
},
{
id: 2,
name: 'Blue Beanie',
imageUrl: 'https://i.ibb.co/ypkgK0X/blue-beanie.png',
price: 18
},
{
id: 3,
name: 'Brown Cowboy',
imageUrl: 'https://i.ibb.co/QdJwgmp/brown-cowboy.png',
price: 35
},
{
id: 4,
name: 'Grey Brim',
imageUrl: 'https://i.ibb.co/RjBLWxB/grey-brim.png',
price: 25
},
{
id: 5,
name: 'Green Beanie',
imageUrl: 'https://i.ibb.co/YTjW3vF/green-beanie.png',
price: 18
},
{
id: 6,
name: 'Palm Tree Cap',
imageUrl: 'https://i.ibb.co/rKBDvJX/palm-tree-cap.png',
price: 14
},
{
id: 7,
name: 'Red Beanie',
imageUrl: 'https://i.ibb.co/bLB646Z/red-beanie.png',
price: 18
},
{
id: 8,
name: 'Wolf Cap',
imageUrl: 'https://i.ibb.co/1f2nWMM/wolf-cap.png',
price: 14
},
{
id: 9,
name: 'Blue Snapback',
imageUrl: 'https://i.ibb.co/X2VJP2W/blue-snapback.png',
price: 16
}
]
},
sneakers:{
id: 2,
title: 'Sneakers',
routeName: 'sneakers',
items: [
{
id: 10,
name: 'Adidas NMD',
imageUrl: 'https://i.ibb.co/0s3pdnc/adidas-nmd.png',
price: 220
},
{
id: 11,
name: 'Adidas Yeezy',
imageUrl: 'https://i.ibb.co/dJbG1cT/yeezy.png',
price: 280
},
{
id: 12,
name: 'Black Converse',
imageUrl: 'https://i.ibb.co/bPmVXyP/black-converse.png',
price: 110
},
{
id: 13,
name: 'Nike White AirForce',
imageUrl: 'https://i.ibb.co/1RcFPk0/white-nike-high-tops.png',
price: 160
},
{
id: 14,
name: 'Nike Red High Tops',
imageUrl: 'https://i.ibb.co/QcvzydB/nikes-red.png',
price: 160
},
{
id: 15,
name: 'Nike Brown High Tops',
imageUrl: 'https://i.ibb.co/fMTV342/nike-brown.png',
price: 160
},
{
id: 16,
name: 'Air Jordan Limited',
imageUrl: 'https://i.ibb.co/w4k6Ws9/nike-funky.png',
price: 190
},
{
id: 17,
name: 'Timberlands',
imageUrl: 'https://i.ibb.co/Mhh6wBg/timberlands.png',
price: 200
}
]
},
jackets:{
id: 3,
title: 'Jackets',
routeName: 'jackets',
items: [
{
id: 18,
name: 'Black Jean Shearling',
imageUrl: 'https://i.ibb.co/XzcwL5s/black-shearling.png',
price: 125
},
{
id: 19,
name: 'Blue Jean Jacket',
imageUrl: 'https://i.ibb.co/mJS6vz0/blue-jean-jacket.png',
price: 90
},
{
id: 20,
name: 'Grey Jean Jacket',
imageUrl: 'https://i.ibb.co/N71k1ML/grey-jean-jacket.png',
price: 90
},
{
id: 21,
name: 'Brown Shearling',
imageUrl: 'https://i.ibb.co/s96FpdP/brown-shearling.png',
price: 165
},
{
id: 22,
name: 'Tan Trench',
imageUrl: 'https://i.ibb.co/M6hHc3F/brown-trench.png',
price: 185
}
]
},
womens:{
id: 4,
title: 'Womens',
routeName: 'womens',
items: [
{
id: 23,
name: 'Blue Tanktop',
imageUrl: 'https://i.ibb.co/7CQVJNm/blue-tank.png',
price: 25
},
{
id: 24,
name: 'Floral Blouse',
imageUrl: 'https://i.ibb.co/4W2DGKm/floral-blouse.png',
price: 20
},
{
id: 25,
name: 'Floral Dress',
imageUrl: 'https://i.ibb.co/KV18Ysr/floral-skirt.png',
price: 80
},
{
id: 26,
name: 'Red Dots Dress',
imageUrl: 'https://i.ibb.co/N3BN1bh/red-polka-dot-dress.png',
price: 80
},
{
id: 27,
name: 'Striped Sweater',
imageUrl: 'https://i.ibb.co/KmSkMbH/striped-sweater.png',
price: 45
},
{
id: 28,
name: 'Yellow Track Suit',
imageUrl: 'https://i.ibb.co/v1cvwNf/yellow-track-suit.png',
price: 135
},
{
id: 29,
name: 'White Blouse',
imageUrl: 'https://i.ibb.co/qBcrsJg/white-vest.png',
price: 20
}
]
},
mens:{
id: 5,
title: 'Mens',
routeName: 'mens',
items: [
{
id: 30,
name: 'Camo Down Vest',
imageUrl: 'https://i.ibb.co/xJS0T3Y/camo-vest.png',
price: 325
},
{
id: 31,
name: 'Floral T-shirt',
imageUrl: 'https://i.ibb.co/qMQ75QZ/floral-shirt.png',
price: 20
},
{
id: 32,
name: 'Black & White Longsleeve',
imageUrl: 'https://i.ibb.co/55z32tw/long-sleeve.png',
price: 25
},
{
id: 33,
name: 'Pink T-shirt',
imageUrl: 'https://i.ibb.co/RvwnBL8/pink-shirt.png',
price: 25
},
{
id: 34,
name: 'Jean Long Sleeve',
imageUrl: 'https://i.ibb.co/VpW4x5t/roll-up-jean-shirt.png',
price: 40
},
{
id: 35,
name: 'Burgundy T-shirt',
imageUrl: 'https://i.ibb.co/mh3VM1f/polka-dot-shirt.png',
price: 25
}
]
}
};
export default SHOP_DATA;
Please provide any pointers or advice on what am I doing wrong? I keep getting the error. It seems that the collection is undefined. I don't understand why. Ideally it should return an object.

You are exporting the component like this
const mapStateToProps = (state,ownProps) => ({
collections: selectCollectionItem(ownProps.match.params.collectionId)(state)
})
export default connect(mapStateToProps)(CollectionPage);
The ownProps.match.params.collectionId might be undefined.
Add this at the top of your file
import { withRouter} from 'react-router-dom'
and export your component like
export default connect(mapStateToProps)(withRouter(CollectionPage));

Related

Mapping through nested arrays in es6 javascript

I have a simple array that I want to group it's objects by date so I used this function
const groupedDates= Object.entries(
items.reduce((acc, { product, price, type, date }) => {
if (!acc[date]) {
acc[date] = [];
}
acc[date].push({ product, price, type date });
return acc;
}, {})
).map(([date, items]) => ({ date, items }));
the array
const items = [
{
id: 1,
product: "milk",
price: 10,
type: "drink"
date: "01/01/2022",
},
{
id: 2,
product: "coca",
price: 11,
type: "drink"
date: "01/01/2022",
},
{
id: 3,
product: "pepsi",
price: 20,
type: "drink"
date: "01/01/2024",
},
{
id: 4,
product: "carrots",
price: 30,
type: "food",
date: "01/01/2023",
},
];
I got this result
{
0: [
date: 01/01/2022,
items : [
0 : {
id: 1,
product: "milk",
price: 10,
type: "drink"
date: "01/01/2022"
}
1 : {
id: 2,
product: "coca",
price: 11,
type: "drink"
date: "01/01/2022",
}
],
1: [
date: "01/01/2024",
items : [
0 : {
id: 3,
product: "pepsi",
price: 20,
type: "drink"
date: "01/01/2024",
}
],
2: [
date: "01/01/2023",
items: [
0:{
id: 4,
product: "carrots",
price: 30,
type: "food",
date: "01/01/2023"
}
]
]
}
Issue:
I cannot seem to figure out how to access items1 when it exists.
What I have tried
is the map below but it only returns the first level of items which is 0 and if I do items1 it returns an error because not all arrays have a second item.
{groupedDates.map((obj) => (
{obj.items[0].product}))}
UPDATE
I'd also like to get the total for each date so I can have a card that has the Date + The total + each item and it's individual price. After getting some help from #Nick, I've managed to output the date, the item and it's price, now I'm still missing the total price for the date.
You need to iterate the items in each obj to get the list of products:
const items = [
{ id: 1, product: "milk", price: 10, type: "drink", date: "01/01/2022" },
{ id: 2, product: "coca", price: 11, type: "drink", date: "01/01/2022" },
{ id: 3, product: "pepsi", price: 20, type: "drink", date: "01/01/2024" },
{ id: 4, product: "carrots", price: 30, type: "food", date: "01/01/2023" },
];
const groupedDates = Object.entries(
items.reduce((acc, { product, price, type, date }) => {
if (!acc[date]) {
acc[date] = [];
}
acc[date].push({ product, price, type, date });
return acc;
}, {})
).map(([date, items]) => ({ date, items }));
const allProducts = groupedDates.map((obj) => obj.items.map(i => i.product))
console.log(allProducts)
const totalsByDate = groupedDates.map(({ date, items }) => (
{ [date] : items.reduce((acc, item) => acc + item.price, 0) }
))
console.log(totalsByDate)
.as-console-wrapper { max-height:100% !important; top 0 }
Note I would make groupedDates an object with its keys being the dates; that will make looking up data for a given date much easier. For example:
const items = [
{ id: 1, product: "milk", price: 10, type: "drink", date: "01/01/2022" },
{ id: 2, product: "coca", price: 11, type: "drink", date: "01/01/2022" },
{ id: 3, product: "pepsi", price: 20, type: "drink", date: "01/01/2024" },
{ id: 4, product: "carrots", price: 30, type: "food", date: "01/01/2023" },
];
const groupedDates = items.reduce((acc, { date, ...rest }) => {
acc[date] = (acc[date] || []).concat({ ...rest })
return acc;
}, {})
console.log(groupedDates)
const allProducts = Object.values(groupedDates)
.flatMap(arr => arr.map(obj => obj.product))
console.log(allProducts)
const totalsByDate = Object.entries(groupedDates).map(([ date, items ]) => (
{ [date] : items.reduce((acc, item) => acc + item.price, 0) }
))
console.log(totalsByDate)
.as-console-wrapper { max-height:100% !important; top 0; }

I am trying to get a function to search an array of objects and then return the entire object based on the filter

I am trying to get my function working and I can not for the life of me figure out why it isnt. I am trying to use .filter() to search the array of objects to find the object with the tag ketchup. Then return the whole object it is in to the console log
let foodArr = [
{
type: 'Chicken',
rating: 1,
tags: ['chicken', 'free-range', 'no hormones'],
price: 10,
popularity: 80
},
{
type: 'pizza',
rating: 5,
tags: ['pepperoni', 'sauce', 'bread'],
price: 25,
popularity: 56
},
{
type: 'hamburger',
rating: 3,
tags: ['bun', 'patty', 'lettuce'],
price: 8,
popularity: 99
},
{
type: 'wings',
rating: 4,
tags: ['wing', 'bbq', 'ranch'],
price: 12,
popularity: 68
},
{
type: 'fries',
rating: 2,
tags: ['ketchup'],
price: 4,
popularity: 100
}
]
const filteredFood = foodArr.filter(function(obj) {
return obj.tags[''] === 'ketchup'
})
console.log(filteredFood)
const filteredFood = foodArr.filter(function(value){
for (let i=0; i<value.tags.length; i++)
if(value.tags[i] === 'ranch'){
return value.tags[i]
}
}
)
console.log(filteredFood)

MUI- Data Grid - Group & Pivot: Keep position & state while updating rows

Currently, I'm putting the Material UI library for React to the test.
I can't preserve my location (scroll) or state (open rows) when I use their Data Grid Group & Pivot function (see example below). It appears to redraw the entire Data Grid.
Is this conceivable, and am I making a mistake?
import { useState, useCallback } from 'react'
import { DataGridPro } from '#mui/x-data-grid-pro';
const DUMMY_ROWS = [
{ path: ['Sarah'], jobTitle: 'CEO', id: 0, key: 0},
{ path: ['Sarah', 'Thomas'], jobTitle: 'Head of Sales', id: 1, key: 1 },
{ path: ['Sarah', 'Thomas', 'Robert'], jobTitle: 'Sales Person', id: 2, key: 2 },
{ path: ['Sarah', 'Thomas', 'Karen'], jobTitle: 'Sales Person', id: 3, key: 3 },
{ path: ['Thomas'], jobTitle: 'CEO', id: 4, key: 4},
{ path: ['Thomas', 'Sarah'], jobTitle: 'Head of Sales', id: 5, key: 5 },
{ path: ['Thomas', 'Sarah', 'Robert'], jobTitle: 'Sales Person', id: 6, key: 6 },
{ path: ['Thomas', 'Sarah', 'Karen'], jobTitle: 'Sales Person', id: 7, key: 7 },
{ path: ['Robert'], jobTitle: 'CEO', id: 8, key: 8},
{ path: ['Robert', 'Thomas'], jobTitle: 'Head of Sales', id: 9, key: 9 },
{ path: ['Robert', 'Thomas', 'Sarah'], jobTitle: 'Sales Person', id: 10, key: 10 },
{ path: ['Robert', 'Thomas', 'Karen'], jobTitle: 'Sales Person', id: 11, key: 11 },
{ path: ['Karen'], jobTitle: 'CEO', id: 12, key: 12 },
{ path: ['Karen', 'Thomas'], jobTitle: 'Head of Sales', id: 13, key: 13 },
{ path: ['Karen', 'Thomas', 'Robert'], jobTitle: 'Sales Person', id: 14, key: 14 },
{ path: ['Karen', 'Thomas', 'Sarah'], jobTitle: 'Sales Person', id: 15, key: 15 },
]
export default function ColumnVirtualizationGrid() {
const [columns, setColumns] = useState([{ field: 'jobTitle', width: 250 }]);
const [rows, setRows] = useState(DUMMY_ROWS)
const removeRow = useCallback(() => {
setRows(prevRows => {
return prevRows.filter(row => row.id !== 3)
})
}, [])
const treePath = useCallback((row) => row.path, [])
return (
<div style={{ height: '100vh', width: '100%' }}>
<button onClick={removeRow}>Remove</button>
<DataGridPro
treeData
getTreeDataPath={treePath}
rows={rows}
columns={columns}
/>
</div>
);
}

Modifying select for product variation in React Js

In a small ecommerce project (sourcing data from WooCommerce) in ReactJs i have a variable product
Besides all the product data i got two array object representing the product variations, one contains all the available attribute and options:
nodes: Array(3)
0:
id: "d2VpZ2h0OjMxOldlaWdodA=="
name: "Weight"
options: Array(2)
0: "250gr"
1: "500gr"
position: 0
variation: true
visible: true
1:
id: "cm9hc3Q6MzE6Um9hc3Q="
name: "Roast"
options: Array(3)
0: "Light"
1: "Medium"
2: "Dark"
position: 1
variation: true
visible: true
2:
id: "cGFja2FnaW5nOjMxOlBhY2thZ2luZw=="
name: "Packaging"
options: Array(2)
0: "Card"
1: "Tin"
position: 2
variation: true
visible: true
I save this one in a state and use it to build the select (3 select in this case)
then i have an array of object which contans all the available combinations, with price, id and so on:
nodes: Array(5)
0:
attributes:
nodes: Array(3)
0: {id: "NDB8fHdlaWdodHx8MjUwZ3I=", name: "weight", value: "250gr"}
1: {id: "NDB8fHJvYXN0fHxNZWRpdW0=", name: "roast", value: "Medium"}
2: {id: "NDB8fHBhY2thZ2luZ3x8Q2FyZA==", name: "packaging", value: "Card"}
id: "cHJvZHVjdF92YXJpYXRpb246NDA="
price: "€7,00"
variationId: 40
1:
attributes:
nodes: Array(3)
0: {id: "Mzh8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "Mzh8fHJvYXN0fHxEYXJr", name: "roast", value: "Dark"}
2: {id: "Mzh8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246Mzg="
price: "€12,00"
variationId: 38
2:
attributes:
nodes: Array(3)
0: {id: "Mzd8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "Mzd8fHJvYXN0fHxNZWRpdW0=", name: "roast", value: "Medium"}
2: {id: "Mzd8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246Mzc="
price: "€12,00"
variationId: 37
3:
attributes:
nodes: Array(3)
0: {id: "MzZ8fHdlaWdodHx8NTAwZ3I=", name: "weight", value: "500gr"}
1: {id: "MzZ8fHJvYXN0fHxMaWdodA==", name: "roast", value: "Light"}
2: {id: "MzZ8fHBhY2thZ2luZ3x8VGlu", name: "packaging", value: "Tin"}
id: "cHJvZHVjdF92YXJpYXRpb246MzY="
price: "€12,00"
variationId: 36
4:
attributes:
nodes: Array(3)
0: {id: "MzR8fHdlaWdodHx8MjUwZ3I=", name: "weight", value: "250gr"}
1: {id: "MzR8fHJvYXN0fHxMaWdodA==", name: "roast", value: "Light"}
2: {id: "MzR8fHBhY2thZ2luZ3x8Q2FyZA==", name: "packaging", value: "Card"}
length: 3
id: "cHJvZHVjdF92YXJpYXRpb246MzQ="
price: "€7,00"
variationId: 34
Basically, when i select something on any select, the other select shoould filter based on the avaialble variations: if i select 250gr as weight, the Dark Roast and the Tin Packaging sould be removed from their select since they arent combinable with 250gr; if i switch back to 500gr (or to "no option selected") they should reappear in the same place as they were before.
on the basic WooCommerce product page it already works this way (you can check its behaviour here: https://shop.popland.it/prodotto/coffee-bean/) but replicating it in ReactJs its harder than i was thinking.
At the moment im stuck on loop that generate the select with an empty onChange handler:
const [attr, setAttr] = useState(product.attributes);
<div>
{attr.nodes.map((attribute, l) => {
return (
<div key={l}>
<span>{attribute.name}</span>
<select
id={attribute.name}
onChange={handleChange}
data-attribute_name={`attribute_${attribute.name}`}
>
<option>Select option</option>
{attribute.options.map((option, o) => {
return (
<option key={o} value={option}>
{option}
</option>
);
})}
</select>
</div>
);
})}
</div>
Any suggetion/help on how to go on from here?
here is my solution.
/src/hooks.js
import { useState } from "react";
import { filterVariations, formatVariations } from "./helpers";
export function useVariations(product) {
const [state, setState] = useState({});
const filteredVariations = filterVariations(
product?.variations?.nodes,
state,
);
const formatedVariations = formatVariations(
filteredVariations,
product?.variations?.nodes,
);
return [formatedVariations, state, setState];
}
/src/helpers.js
export function filterVariations(variations, state) {
if (Object.keys(state).length === 0) {
return variations;
}
return Object.keys(state)?.reduce((accStateVars, currStateVar) => {
return accStateVars.reduce((accVars, currVar) => {
const filteredAttrsByName = currVar?.attributes?.nodes?.filter(
(attr) => currStateVar === attr?.name,
);
const withSelected = currVar?.attributes?.nodes?.findIndex(
(attr) => attr?.attributeId === state?.[currStateVar]?.value,
);
return [
...accVars,
{
attributes: {
nodes:
withSelected >= 0
? currVar?.attributes?.nodes
: filteredAttrsByName,
},
},
];
}, []);
}, variations);
}
export function formatVariations(filteredVariations, variations) {
const defaultSelects = variations?.reduce(
(accVars, currVar) => ({
...accVars,
...currVar?.attributes?.nodes?.reduce(
(accAttrs, currAttr) => ({ ...accAttrs, [currAttr.name]: {} }),
{},
),
}),
{},
);
return filteredVariations.reduce((accVars, currVar) => {
const filteredAttrs = currVar?.attributes?.nodes?.reduce(
(accAttrs, currAttr) => {
const exists =
0 <=
accVars[currAttr.name]?.options?.findIndex(
(option) => option.value === currAttr.attributeId,
);
return {
...accAttrs,
[currAttr.name]: {
placeholder: currAttr.label,
options: exists
? accVars[currAttr.name]?.options || []
: [
...(accVars[currAttr.name]?.options || []),
{ label: currAttr.value, value: currAttr.attributeId },
],
},
};
},
{},
);
return { ...accVars, ...filteredAttrs };
}, defaultSelects);
}
/src/App.js
import "./styles.css";
import Select from "react-select";
import { useVariations } from "./hooks";
const product = {
variations: {
nodes: [
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY5MHx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 304,
id: "NTY5MHx8cGFfY29sb3J8fGdyYXBoaXRl",
label: "Color",
value: "Graphite",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY5MHx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY5MHx8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 255,
id: "NTY4Nnx8cGFfc2l6ZXx8MTAtc3BlYWtlcg==",
label: "Size",
value: '10" Speaker',
},
{
name: "pa_color",
attributeId: 67,
id: "NTY4Nnx8cGFfY29sb3J8fGJlaWdl",
label: "Color",
value: "Beige",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY4Nnx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 337,
id: "NTY4Nnx8cGFfcGFsbGV0fHxwZWFjaA==",
label: "Pallet",
value: "Peach",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 255,
id: "NTY4N3x8cGFfc2l6ZXx8MTAtc3BlYWtlcg==",
label: "Size",
value: '10" Speaker',
},
{
name: "pa_color",
attributeId: 439,
id: "NTY4N3x8cGFfY29sb3J8fGZhdGFsLWFwcGxl",
label: "Color",
value: "Fatal Apple",
},
{
name: "pa_flavor",
attributeId: 319,
id: "NTY4N3x8cGFfZmxhdm9yfHx2YW5pbGxh",
label: "Flavor",
value: "Vanilla",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY4N3x8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY4OHx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 67,
id: "NTY4OHx8cGFfY29sb3J8fGJlaWdl",
label: "Color",
value: "Beige",
},
{
name: "pa_flavor",
attributeId: 320,
id: "NTY4OHx8cGFfZmxhdm9yfHxnb2xk",
label: "Flavor",
value: "Gold",
},
{
name: "pa_pallet",
attributeId: 337,
id: "NTY4OHx8cGFfcGFsbGV0fHxwZWFjaA==",
label: "Pallet",
value: "Peach",
},
],
},
},
{
attributes: {
nodes: [
{
name: "pa_size",
attributeId: 254,
id: "NTY4OXx8cGFfc2l6ZXx8MTItc3BlYWtlcg==",
label: "Size",
value: '12" Speaker',
},
{
name: "pa_color",
attributeId: 436,
id: "NTY4OXx8cGFfY29sb3J8fGJlbGdyYXZlcw==",
label: "Color",
value: "Belgraves",
},
{
name: "pa_flavor",
attributeId: 319,
id: "NTY4OXx8cGFfZmxhdm9yfHx2YW5pbGxh",
label: "Flavor",
value: "Vanilla",
},
{
name: "pa_pallet",
attributeId: 336,
id: "NTY4OXx8cGFfcGFsbGV0fHxncmVlbg==",
label: "Pallet",
value: "Green",
},
],
},
},
],
},
};
export default function App() {
const [selects, state, setState] = useVariations(product);
function onChange(select, value) {
const newState = {
...state,
[select]: { ...value, name: select },
};
if (!value) {
delete newState[select];
}
setState(newState);
}
return (
<div className="App">
{Object.keys(selects).map((select) => (
<Select
isClearable
key={selects[select].placeholder}
placeholder={selects[select].placeholder}
// value={state[select]}
onChange={(o) => onChange(select, o)}
options={selects[select].options}
/>
))}
</div>
);
}
Playground

How can I build model data?

I was asked to create a mini amazon web app and as model data, I was told to use the below code. const items is products sold in the mini amazon and const promotion is a seperate data for all promotion each user get. Where do I store itemsAvailable.js and promotion.js so that I can fetch those in react components?
// itemsAvailable.js
const items = [
{
id: '123',
title: 'product1',
coverImage: 'public.jpg',
price: 20,
score: 20,
},
{
id: '123123',
title: 'product2',
coverImage: 'public2.jpg',
price: 30,
score: 30,
},
];
// promotion.js
const promotion = [
{
type: 'sale',
title: '30%',
rate: 30,
},
];
One way is using state,
constructor(props){
super(props);
this.state = {
item: [{
id: '123',
title: 'product1',
coverImage: 'public.jpg',
price: 20,
score: 20,
},
{
id: '123123',
title: 'product2',
coverImage: 'public2.jpg',
price: 30,
score: 30,
}
],
promotion: [{
type: 'sale',
title: '30%',
rate: 30,
}
]
}
}
Usage,
{
this.state.item.map((item)=>{
<div>{item.id}</div>
....
})
}
Likewise you can use promotion array.

Resources