Getting Undefined while accessing the values of data object inside map in Next.js - javascript

// while accessing the object values from data, I'm getting undefined in map
// ../data/section1
const data = [{
id: 1,
image: './images/homepage/xbox-games.png',
text: 'Buy Xbox games and consoles',
}, {
id: 2,
image: './images/homepage/shop_surface_devices.webp',
text: 'Shop surface devices',
}, {
id: 3,
image: './images/homepage/choose_your_ms_365.png',
text: 'Choose your Microsoft 365',
}, {
id: 4,
image: './images/homepage/shop_windows_10.png',
text: 'Shop Windows 10',
}]
export default data;
// the actual component
import data from "../data/section1";
const Section1 = () => {
return (
<>
<div class="mx-20">
{data.map((vals) => {
<div class="">
<img src={vals.image}/>
<p>{vals.text}</p>
</div>
})}
</div>
</>
)
}
export default Section1;

return JSX from the map
import data from "../data/section1";
const Section1 = () => {
return (
<>
<div class="mx-20">
{data.map((vals) => {
return (
<div class="">
<img src={vals.image}/>
<p>{vals.text}</p>
</div>
)
})}
</div>
</>
)
}
export default Section1;

I had the same problem, then tried the first bracket instead of the second, and it resolved the problem
import data from "../data/section1";
const Section1 = () => {
return (
<>
<div class="mx-20">
{data.map((vals) => (
<div class="">
<img src={vals.image}/>
<p>{vals.text}</p>
</div>
))}
</div>
</>
)
}
export default Section1;

Related

Image is not showing in React app using img tag

My image is not showing in React app. I am trying to fetch the path from JSON and pass the path using props in <img> tag.
Example JSON object with the product data:
let data = [
{
id: 1,
name: "Striped Slim Fit Shirt",
image: "./Assets/m1.jpg",
price: 1000,
category: "Men",
size: "XL",
inStock: true,
},
{
id: 2,
name: "Full Sleeves Slim Fit Shirt",
image: "./Assets/m2.jpg",
price: 2000,
category: "Men",
size: "L",
inStock: true,
},
];
export default data;
My parent component from which I am passing props.
import { Fragment } from "react";
import data from "../../DUMMY_DATA";
import ItemList from "./ItemList";
const HomePage = () => {
const availableItems = data.map((products) => (
<ItemList
key={products.id}
images={products.image}
name={products.name}
price={products.price}
category={products.category}
size={products.size}
/>
));
return (
<Fragment>
<div>{availableItems}</div>
</Fragment>
);
};
export default HomePage;
My child component. Here, console logging shows the correct path, but the <img> tag is not rendering it.
import { Fragment } from "react";
const ItemList = (props) => {
const { id, images, name, price, category, size, inStock } = props;
return (
<Fragment>
<div className="container text-center">
<div className="row row-cols-4" key={id}>
<div className="col">
<img src={images} />
</div>
<div className="col">{name}</div>
<div className="col">{size}</div>
<div className="col">{price}</div>
</div>
</div>
</Fragment>
);
};
export default ItemList;

Mapping data in a JSX Component

I'm trying to render a Card component dynamically mapped from an array of objects.
The issue is I'm getting an "unexpected token error ..." And URL won't render. I should see five cards display based on the data inside the array, but it throws an error. Does anyone see where I'm going wrong? I'm using React 18 if that matters.
Component code:
import React from "react";
import links from "../links";
function Card (props) {
return (
<div>
<div className="link-container">
<div className="row">
<div className="card">
<hr className="divide"></hr>
<img className="img" src={props.img} alt="social-icon" />
<h4>{props.name}</h4>
</div>
</div>
</div>
</div>
)
}
Data:
const links = [
{
id: 1,
name: "Youtube",
img:"./img/youtube.svg",
href: "https://www.youtube.com/c/SubwaySounds"
},
{
id: 2,
name: "Spotify",
img:"./img/spotify.svg",
href: "https://artists.spotify.com/c/artist/3DM32kjsG7Pp5EM7o3Uv7t/profile/overview"
},
{
id: 3,
name: "Tiktok",
img:"./img/tiktok.svg",
href: "https://www.tiktok.com/#nysubwaysounds"
},
{
id: 4,
name: "Instagram",
img:"./img/instagram.svg",
href: "https://www.instagram.com/nycsubwaysounds/?hl=en"
},
{
id: 5,
name: "Shop",
img:"./img/shop.svg",
href: "https://my-store-11524143.creator-spring.com/"
}
]
export default links;
App.jsx:
import Header from "./Header";
import Card from "./Card";
import links from "../links";
function CreateCard (socialLinks) {
return (
<Cards
key= {socialLinks.id}
img= {socialLinks.img}
name= {socialLinks.name}
href= {socialLinks.href}
/>
)
}
function App() {
return (
<div>
<Header />
<Card {links.map(createCard)} />
</div>
);
}
export default App;
use the React map method
function App() {
return (
<div>
<Header />
{
links.map((link, linkKey) => (
<Card
key={linkKey}
img= {socialLinks.img}
name= {socialLinks.name}
href= {socialLinks.href}
/>
))
}
</div>
);
}

Unable to successfully loop through a redux store after a dispatch function

I'm trying to add product items to my redux store called cart. After adding an item I then compare both stores product(redux store) and cart(redux store) to check if the product has the same itemCode(item code. if they do I would like to Hide the add button and show the remove button. Unfortunately I'm getting different results, please look at the picture below for reference:
interface IProps {
items: ItemInterface[];
documentItems: ItemInterface[];
onAddItem: any;
}
const ItemFlatList2: FC<Partial<IProps>> = ({
items,
documentItems,
onAddItem,
}) => {
return (
<div className={styles.container}>
<ul>
{items!.map((item) => {
return (
<div className={styles.itemContainer}>
<div key={item.itemCode}>
<li>{item.itemCode}</li>
<li>{item.itemDescription}</li>
{documentItems!.length === 0 ? (
<AddButton
title={"ADD"}
onClick={() =>
onAddItem(
item.itemCode,
item.itemDescription,
item.itemSellingPrice
)
}
/>
) : (
documentItems!.map((documentItem) => {
if (documentItem.itemCode === item.itemCode) {
return <RedButton title={"Remove"} />;
}
if (documentItem.itemCode !== item.itemCode) {
return (
<AddButton
title={"ADD"}
onClick={() =>
onAddItem(
item.itemCode,
item.itemDescription,
item.itemSellingPrice
)
}
/>
);
}
})
)}
</div>
<div>
<li>Hello world</li>
</div>
</div>
);
})}
</ul>
</div>
);
};
export default ItemFlatList2;
The Cart Store:
const initialState: Partial<DocumentDetailsInterface>[] = [
];
const cartStore = createSlice({
name: "quotation reducer",
initialState,
reducers: {
add: {
reducer: (
state,
{ payload }: PayloadAction<DocumentDetailsInterface>
) => {
state.push(payload);
},
prepare: (item) => ({
payload: item,
}),
},
edit: (state, { payload }) => {},
remove: (
state,
{ payload }: Partial<PayloadAction<DocumentDetailsInterface>>
) => {
const findItem = state.findIndex((item) => payload!.code === item.code);
if (findItem !== 1) {
state.splice(findItem, 1);
}
},
},
extraReducers: {},
});
and The Product Store:
const initialState: ItemInterface[] = [
{
_id: "sdfsd",
itemType: "Physical Item",
itemUnitOfMeasure: "Unit",
itemCode: "PPC10",
itemDescription: "PPC Cement",
itemCostPrice: 50,
itemSellingPrice: 80,
itemQuantity: 100,
vatStatus: "Standard rate 15%",
},
{
_id: "qew",
itemType: "Physical Item",
itemUnitOfMeasure: "Unit",
itemCode: "2",
itemDescription: "Sepako Cement",
itemCostPrice: 30,
itemSellingPrice: 60,
itemQuantity: 100,
vatStatus: "Standard rate 15%",
},
{
_id: "sdfsd",
itemType: "Physical Item",
itemUnitOfMeasure: "Unit",
itemCode: "1",
itemDescription: "PPC Cement",
itemCostPrice: 50,
itemSellingPrice: 80,
itemQuantity: 100,
vatStatus: "Standard rate 15%",
},
];
const itemSlice = createSlice({
name: "item reducer",
initialState,
reducers: {},
extraReducers: {},
});
It looks like you have wrong logic in you render method. You displayed "Add" button when there are no items in documentItems and the if any items inside you keep adding "Add" buttons if they are not equal to itemCode. So basically you have 2 loops. First is render items, and second one is to render buttons for each item. But you can use one loop to render items and have logic to check if that item is already in the documentItems array - if not then display "Add" button, else "Remove" button.
return (
<div className={styles.container}>
<ul>
{items!.map(item => {
return (
<div className={styles.itemContainer} key={item.itemCode}>
<div key={item.itemCode}>
<li>{item.itemCode}</li>
<li>{item.itemDescription}</li>
{documentItems!.findIndex(
documentItem => documentItem.itemCode === item.itemCode,
) === -1 ? (
<AddButton
title={'ADD'}
onClick={() =>
onAddItem(
item.itemCode,
item.itemDescription,
item.itemSellingPrice,
)
}
/>
) : (
<RedButton title={"Remove"} />
)}
</div>
<div>
<li>Hello world</li>
</div>
</div>
);
})}
</ul>
</div>
);
I think you need to provide a unique key to button. Write the statemen when you are changing the state
<AddButton
title={"ADD"}
key={item.itemCode}
onClick={() =>
onAddItem(
item.itemCode,
item.itemDescription,
item.itemSellingPrice
)
}
/>
You used map function to check if item exists in the documentItems. I think changing it to some function will work out.
documentItems!.some((documentItem) => {
return documentItem.itemCode === item.itemCode
}
) ? (<RedButton title={"Remove"} />): (
<AddButton
title={"ADD"}
onClick={() =>
onAddItem(
item.itemCode,
item.itemDescription,
item.itemSellingPrice
)
}
/>
);

How to Show/Hide nested array element/component after mapping outer array with useState in React?

Initial objective:
I have 4 components, when clicking on one of the components, the other three components disappear to only show the one that is clicked. Clicking on the component again toggles all the components to display again.
My goal is to add an info/description object to each of the components in the array so that when a component is toggled, the other components still disappear but now a description shows up in accordance with the toggled component.
My thought process is to set a visibility flag to the description element, set it to false, and toggling a specific component will change the flag to true and have the description appear.
Here is my current take on it:
const array = [
{ id: 1, component: <Comp1/>, isVisible: true,
info: [{ id: 5, component: <div>info1</div>, isVisibleInfo: false }] },
{ id: 2, component: <Comp2/>, isVisible: true,
info: [{ id: 6, component: <div>info2</div>, isVisibleInfo: false }] },
{ id: 3, component: <Comp3/>, isVisible: true,
info: [{ id: 7, component: <div>info3</div>, isVisibleInfo: false }] },
{ id: 4, component: <Comp4/>, isVisible: true,
info: [{ id: 8, component: <div>info4</div>, isVisibleInfo: false }] }
];
export const Test = () => {
const [items, setItems] = useState(array);
const handleClick = (number) => {
const triggeredItems = items.map((item) => {
if (item.id !== number) {
item.isVisible = !item.isVisible;
}
return item;
});
setItems(triggeredItems);
};
const handleClickInner = (number) => {
const triggeredItemsInner = items.info.map((item) => {
if (item.id !== number) {
item.isVisibleInfo = !item.isVisibleInfo;
}
return item;
});
setItems(triggeredItemsInner);
};
return (
<div className="mt-1 pt-1 pb-3 px-3">
<div className="row text-center d-flex my-1">
{items.map(({ id, component, isVisible, info }) => (
<div
key={id}
className="col-lg-3 col-md-6 mb-4 justify-content-center"
onClick={() => handleClick(id)}
hidden={!isVisible}
>
{ component }
{info.map(({ id, component, isVisibleInfo }) => (
<div
key={id}
className="col-lg-9 col-md-6 mb-4 justify-content-center"
onClick={() => { handleClickInner(id)}}
hidden={isVisibleInfo}
>
{ component }
</div>
))}
</div>
))}
</div>
</div>
);
};
export default Test;
At the moment, I am getting this output TypeError: Cannot read property 'map' of undefined in the 'handleClickInner function because I believe map cannot map a nested array, but in general I am not sure if creating this second function is the right approach even.
Still learning a lot about React and it's methods!
Any thoughts or help would appreciated!
My goal is to add an info/description object to each of the components
in the array so that when a component is toggled, the other components
still disappear but now a description shows up in accordance with the
toggled component.
You dont really mean disappear do you? sounds more like you want to conditionally render the component.
UPDATED
I misunderstood your intentions! Now they disappear.
// hooks
const {useState} = React;
function Comp1(){
return <div><p>Component 1</p></div>
}
function Comp2(){
return <div><p>Component 2</p></div>
}
function Comp3(){
return <div><p>Component 3</p></div>
}
function Comp4(){
return <div><p>Component 4</p></div>
}
const array = [
{ id: 1, component: <Comp1/>, isVisible: true,
info: { id: 5, component: <div>info1</div>, isVisibleInfo: false } },
{ id: 2, component: <Comp2/>, isVisible: true,
info: { id: 6, component: <div>info2</div>, isVisibleInfo: false } },
{ id: 3, component: <Comp3/>, isVisible: true,
info: { id: 7, component: <div>info3</div>, isVisibleInfo: false } },
{ id: 4, component: <Comp4/>, isVisible: true,
info: { id: 8, component: <div>info4</div>, isVisibleInfo: false } }
];
const Test = () => {
const [items, setItems] = useState(array);
const handleClick = (number) => {
const triggeredItems = items.map((item) => {
if (item.id !== number) {
item.isVisible = !item.isVisible;
}
item.info.isVisibleInfo =! item.info.isVisibleInfo
return item;
});
setItems(triggeredItems);
};
return (
<div className="mt-1 pt-1 pb-3 px-3">
<div className="row text-center d-flex my-1">
{items.map(({ id, component, isVisible, info }) => (
isVisible ?
<div
key={id}
className="col-lg-3 col-md-6 mb-4 justify-content-center"
onClick={() => handleClick(id)}
hidden={!isVisible}
>
{ component }
{info.isVisibleInfo ?
<div
key={info.id}
className="col-lg-9 col-md-6 mb-4 justify-content-center"
>
{ info.component }
</div>
: null}
</div>
: null
))}
</div>
</div>
);
};
function App(){
return (
<div>
<Test />
</div>
);
};
// Render
ReactDOM.render(
<App />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

Multiple array check react js

I have an array of objects which I'm rendering by section - see title of each object "Price", "Sectors and Charges" etc.
This populates a mini modal where users can select options to update rendered columns basically a filter.
The selection of the items are working however if I make a selection of the first item "0" all sections with the first option are selected.
How can I store the selection from each object into the selectedOptions array?
Please note I'm using react js and styled components, I've not added the styled component code.
Data:
const columnsData = [
{
title: 'Price',
options: [
{
label: 'Daily Change'
},
{
label: 'Price'
},
{
label: 'Price Date'
},
{
label: 'Volatility Rating'
}
],
},
{
title: 'Sectors and Charges',
options: [
{
label: 'Sector'
},
{
label: 'Asset Class'
},
{
label: 'AMC'
},
],
},
{
title: 'Cumulative Performance',
options: [
{
label: '1 month'
},
{
label: '6 months'
},
{
label: '1 year'
},
],
},
]
Code:
const EditColumns = ({active, onClick}) => {
const [selectedOptions, setSelectedOptions] = useState([0, 1, 2]);
const update = () => {
onClick();
}
const updateSelection = (z) => {
setSelectedOptions(selectedOptions.includes(z) ? selectedOptions.filter(j => j !== z) : [...selectedOptions, z]);
}
return (
<Wrap onClick={() => update()}>
<CTA>
<SVG src="/assets/svgs/btns/edit.svg" />
<span>Columns</span>
</CTA>
{active &&
<Dropdown>
<Head>
<span className="title">Edit Columns</span>
<span>Select the columns you would like to see</span>
</Head>
<Body>
{columnsData.map((item, i) => {
return (
<Section key={i}>
<SectionHead>
<span className="title">{item.title}</span>
<span>Select all</span>
</SectionHead>
<SectionList>
{item.options.map((child, z) => {
const selected = selectedOptions.includes(z);
return (
<li key={z} className={classNames({selected})} onClick={() => updateSelection(z)}>
<span>{child.label}</span>
</li>
)
})}
</SectionList>
</Section>
)
})}
</Body>
</Dropdown>
}
</Wrap>
)
}
export default EditColumns;
Your section lists are all sharing the same state variable, so any changes will be applied to all of them. You could fix this either by constructing a more complex state object which more closely resembles the structure of columnsData, or making each SectionList its own component with its own state. What you decide to do will depend on the degree to which the EditButtons component actually needs access to the whole state.
The second approach might look something like this:
const EditColumns = ({active, onClick}) => {
const update = () => {
onClick();
}
return (
<Wrap onClick={() => update()}>
<CTA>
<SVG src="/assets/svgs/btns/edit.svg" />
<span>Columns</span>
</CTA>
{active &&
<Dropdown>
<Head>
<span className="title">Edit Columns</span>
<span>Select the columns you would like to see</span>
</Head>
<Body>
{columnsData.map((item, i) => {
return (
<Section key={i}>
<SectionHead>
<span className="title">{item.title}</span>
<span>Select all</span>
</SectionHead>
<SectionList options={item.options}/>
</Section>
)
})}
</Body>
</Dropdown>
}
</Wrap>
)
}
const SectionList = ({options}) => {
const [selectedOptions, setSelectedOptions] = useState([0, 1, 2]);
const updateSelection = (z) => {
setSelectedOptions(selectedOptions.includes(z) ? selectedOptions.filter(j => j !== z) : [...selectedOptions, z]);
}
return (
<SectionListContainer>
{options.map((child, z) => {
const selected = selectedOptions.includes(z);
return (
<li key={z} className={classNames({selected})} onClick={() => updateSelection(z)}>
<span>{child.label}</span>
</li>
)
})}
</SectionListContainer>
)
}

Categories