How to iterate data from array? - reactjs

I'm developing a Products page using React. I have setup data like this
const data = {
items: [
{
id: 1,
name: 'Alloha Zune',
brand: 'Alloha',
slug: 'asus-zune-4',
price: '90$',
image: '/images/alloha_zune.png',
category: 'Alloha',
},
{
id: 2,
name: 'Bacleim Pro',
brand: 'Bacleim',
slug: 'bacleim-pro',
price: '110$',
image: '/images/bacleim_pro.jpg',
category: 'Bacleim',
},
{
id: 3,
name: 'Xarin Makeshift',
brand: 'Xarin',
slug: 'xarin-makeshift',
price: '120$',
image: '/images/xarin_makeshift.png',
category: 'Xarin',
},
],
};
export default data;
I want to iterate these items as cards using reusable components.
The card component is as follows:
export default function Card() {
return (
<div>
<>
<div>
<img
src={item.image}
alt={item.name}
/>
<div>
<h2>{item.name}</h2>
<p>{item.price}</p>
<ul>
<p>{item.brand}</p>
<p>{item.category}</p>
</ul>
<button type="submit" className="primary-button">
Buy
</button>
</div>
</div>
</>
</div>
);
}
And I want to create another component such CardList Component to iterate over the data.
What will be the most code-efficient way to do this in React?

Create a reusable Product Component and you can pass data to it in the form of props, like this
return (
<div>
{data.items.map(product => {
return <ProductComponent ...product />
})}
</div>
)
Note I'm spreading the product object so that all the key-value pairs are passed to the component in the form of props

You can map over the data.items and pass required props to Card component.
CODESANDBOX DEMO
export default function App() {
return (
<>
{data.items.map((product) => {
const { id, ...rest } = product;
return <Card {...rest} key={id} />;
})}
</>
);
}

Related

Mapping links to components

I'm learning to react and wanted to create a card that, when clicked, routes the user to an external web page. I haven't seen any tutorials or explanations on this all I keep finding is for internal website navigation. I tried doing this in different ways but can't find the correct way to do this.
my component:
import React from "react";
function Card (props) {
const handleClick = () => {
return
}
return (
<div>
}
<div className="link-container" onClick= {()=> {
return handleClick();}
}>
<div className="row">
<div className="card">
<hr className="divide"></hr>
<img className="img" src={props.img} alt="social-icon" />
<h4 className="name">{props.name}</h4>
</div>
</div>
</div>
</div>
)
}
export default Card;
href links to be used:
const links = [
{
id: 1,
name: "Youtube",
img:"./img/youtube1.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/Instagram1.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;
What you need to do is to create an element for each item for the list. For this, you can use the builtin JS map function.
For example, you can create a new variable holding the elements:
const linksElements = links.map(item => (<Card item={item} />));
and use it with {linksElements} inside of the return value.
I've created this as an example using your list: https://stackblitz.com/edit/react-yt1hfl?file=src/App.js. Note that this is a quick and dirty implementation, without any other components.

Props is not updating in class component React

I am Traying to pass props as product data object on clicking on that product in class component in react but element values are not getting assigned the following code for which am trying for plz help to solve this problem I am new at class component in react
class ProductList extends React.Component {
constructor() {
super()
this.state = {
product:undefined,
productsList: [
{
id: 1,
name: 'Samsung Galaxy Note 10',
category: 'Mobiles',
country: 'Canada',
price: 11500,
currencyCode: 'CAD',
productImage: require('./assets/img/product1.jpg'),
},
{
id: 5,
name: 'SkullCandy BT Inkd Plus',
category: 'Bluetooth Headset',
country: 'UK',
price: 800,
currencyCode: 'USD',
productImage: require('./assets/img/product2.jpg'),
}
],
}
}
render() {
return (
<>
<div className="ProductList">
<ul id="products" className="products">
{this.state.productsList.map((element, i) => (
<li
id={'product' + i}
onClick={() => this.setState({ product: 'abc' })}
>
<img id={'image' + i} src={element.productImage} />
<b>{element.name}</b>
</li>
))}
</ul>
</div>
<div className="productComponent">
{console.log(this.product)}
<Product productProp={this.product} />
</div>
</>
)
}
}
export default ProductList
Pass props as this.state.product instead of this.product
<Product productProp={this.state.product} />

style react component on click

so i have this simple divs of names:
i just want to press on one of them and get a background color of green and when pressing on another one the first one will be canceled so just one will be colored at a time. what i simply need is inline style or i don't know i'm stuck.
first.js:
import React from 'react';
function SidebarComponents({name,title,selected,onSelect}) {
const style={
cursor: "pointer"
};
const classes = {
selected: {
backgroundColor: '#00ff00'
}
}
return (
<div
name={name}
title = {title}
style={style}
>
{name}
</div>
)
}
export default SidebarComponents;
second.js:
import React, { useEffect, useState } from "react";
import SidebarComponents from "../SidebarComponents/SidebarComponents";
import 'bootstrap/dist/css/bootstrap.min.css';
import '../Sidebar1/Sidebar.css';
function Sidebar({ onChange }) {
const [selectedComponent, setSelectedComponent] = useState({
componentsName: [
{ name: "John Smith", title: "John Smith" },
{ name: "Male, 26 years old", title: "Gender and age" },
{ name: "john", title: "Alerts" },
{ name: "claude", title: "Recent" },
{ name: "edward", title: "Blood pressure" },
{ name: "mira", title: "Body weight" },
{ name: "alex", title: "Glucose" },
{ name: "zac", title: "SPO2" }
]
});
return (
<div>
{selectedComponent.componentsName.map(component => {
return (
<div className="row align-items-start sidebar-components">
<div className="col">
<SidebarComponents
name={component.name}
title={component.title}
/>
</div>
</div>
);
})}
</div>
);
}
export default Sidebar;
on Sidebar:
const [selectedName, setSelectedName] = useState(null);
//...
<SidebarComponents
name={component.name}
title={component.title}
selected={component.name === selectedName}
onSelect={setSelectedName}
/>
on SidebarComponents:
const selectedClassName = selected ? 'selected' : '';
//...
<div
name={name}
title={title}
style={style}
className={`sidebar ${selectedClassName}`} //you must add sidebar and selected classes to your styles
onClick={() => onSelect(name)}
>
{name}
</div>
Add key attribute to div, inside the map.
Handel onClick event, to store the selected element index/value in your state.
Apply style using conditional rendering of className.
second.js
<div>
{selectedComponent.componentsName.map((component, index) => {
return (
<div key={index} onClick={() => handelOnClick(index)} className="row align-items-start sidebar-components">
<div className="col">
<SidebarComponents
name={component.name}
title={component.title}
className={selectedIndex === index ? 'highlight' : ''}
/>
</div>
</div>
);
})}
</div>
As you are rendering text in first.js no need to use div wrapper, use 'p', 'span' tag
In second.js instead of iterating entire div block, use ul li

How to pass multiple arguments through React Context (from Consumer to Provider)?

I am creating a simple app using create-react-app
And was exploring using React Context API to pass few stuff from one component to another component.
Spice.js
const spiceList = [
{
id: 1,
title: 'Spice 11',
name: require('./images/spice1.jpeg')
},
{
id: 2,
title: 'Spice 22',
name: require('./images/spice2.jpeg')
}
];
return (
<div>
<h1>Welcome to Spices</h1>
<SpiceContext.Provider value={'Masala'} imgSrc={img3}>
<SpiceList/>
</SpiceContext.Provider>
</div>
</div>
);
}
}
export default Spice;
Consumer in SpiceList Where I plan to retrieve multiple attributes instead of a single value attribute.
How this could be achieved? Thanks
<>
<h1>{props.title}</h1>
<SpiceContext.Consumer>
{spiceContext=> <img src={spiceContext.value} alt={spiceContext.title}/>
}
</SpiceContext.Consumer>
</>
SpiceContext
import React from 'react';
const SpiceContext = React.createContext(null);
export default SpiceContext;
First create your object to share.
const myOptions = [
{
key: 1,
title: 'Title',
other: 'other',
},
{
key: 2,
title: 'Title',
other: 'other',
}
];
Then pass it down.
return (
<div>
<h1>Welcome to Spices</h1>
<SpiceContext.Provider value={myOptions} imgSrc={img3}>
<SpiceList/>
</SpiceContext.Provider>
</div>
</div>
);
Then you will receive those in the same way:
<h1>{props.title}</h1>
<SpiceContext.Consumer>
{(options) => (
<>
{options.map((option) => (
<img key={option.key} src={option.other} alt={option.title}/>
))}
</>
)}
</SpiceContext.Consumer>

Iterate Item Inside JSX React Native [duplicate]

could you please tell me how to render a list in react js.
I do like this
https://plnkr.co/edit/X9Ov5roJtTSk9YhqYUdp?p=preview
class First extends React.Component {
constructor (props){
super(props);
}
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>;
return (
<div>
hello
</div>
);
}
}
You can do it in two ways:
First:
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>);
return (
<div>
{listItems }
</div>
);
}
Second: Directly write the map function in the return
render() {
const data =[{"name":"test1"},{"name":"test2"}];
return (
<div>
{data.map(function(d, idx){
return (<li key={idx}>{d.name}</li>)
})}
</div>
);
}
https://facebook.github.io/react/docs/jsx-in-depth.html#javascript-expressions
You can pass any JavaScript expression as children, by enclosing it within {}. For example, these expressions are equivalent:
<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>
This is often useful for rendering a list of JSX expressions of arbitrary length. For example, this renders an HTML list:
function Item(props) {
return <li>{props.message}</li>;
}
function TodoList() {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
<ul>
{todos.map((message) => <Item key={message} message={message} />)}
</ul>
);
}
class First extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [{name: 'bob'}, {name: 'chris'}],
};
}
render() {
return (
<ul>
{this.state.data.map(d => <li key={d.name}>{d.name}</li>)}
</ul>
);
}
}
ReactDOM.render(
<First />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Shubham's answer explains very well. This answer is addition to it as per to avoid some pitfalls and refactoring to a more readable syntax
Pitfall : There is common misconception in rendering array of objects especially if there is an update or delete action performed on data. Use case would be like deleting an item from table row. Sometimes when row which is expected to be deleted, does not get deleted and instead other row gets deleted.
To avoid this, use key prop in root element which is looped over in JSX tree of .map(). Also adding React's Fragment will avoid adding another element in between of ul and li when rendered via calling method.
state = {
userData: [
{ id: '1', name: 'Joe', user_type: 'Developer' },
{ id: '2', name: 'Hill', user_type: 'Designer' }
]
};
deleteUser = id => {
// delete operation to remove item
};
renderItems = () => {
const data = this.state.userData;
const mapRows = data.map((item, index) => (
<Fragment key={item.id}>
<li>
{/* Passing unique value to 'key' prop, eases process for virtual DOM to remove specific element and update HTML tree */}
<span>Name : {item.name}</span>
<span>User Type: {item.user_type}</span>
<button onClick={() => this.deleteUser(item.id)}>
Delete User
</button>
</li>
</Fragment>
));
return mapRows;
};
render() {
return <ul>{this.renderItems()}</ul>;
}
Important : Decision to use which value should we pass to key prop also matters as common way is to use index parameter provided by .map().
TLDR; But there's a drawback to it and avoid it as much as possible and use any unique id from data which is being iterated such as item.id. There's a good article on this - https://medium.com/#robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318
Try this below code in app.js file, easy to understand
function List({}) {
var nameList = [
{ id: "01", firstname: "Rahul", lastname: "Gulati" },
{ id: "02", firstname: "Ronak", lastname: "Gupta" },
{ id: "03", firstname: "Vaishali", lastname: "Kohli" },
{ id: "04", firstname: "Peter", lastname: "Sharma" }
];
const itemList = nameList.map((item) => (
<li>
{item.firstname} {item.lastname}
</li>
));
return (
<div>
<ol style={{ listStyleType: "none" }}>{itemList}</ol>
</div>
);
}
export default function App() {
return (
<div className="App">
<List />
</div>
);
}
import React from 'react';
class RentalHome extends React.Component{
constructor(){
super();
this.state = {
rentals:[{
_id: 1,
title: "Nice Shahghouse Biryani",
city: "Hyderabad",
category: "condo",
image: "http://via.placeholder.com/350x250",
numOfRooms: 4,
shared: true,
description: "Very nice apartment in center of the city.",
dailyPrice: 43
},
{
_id: 2,
title: "Modern apartment in center",
city: "Bangalore",
category: "apartment",
image: "http://via.placeholder.com/350x250",
numOfRooms: 1,
shared: false,
description: "Very nice apartment in center of the city.",
dailyPrice: 11
},
{
_id: 3,
title: "Old house in nature",
city: "Patna",
category: "house",
image: "http://via.placeholder.com/350x250",
numOfRooms: 5,
shared: true,
description: "Very nice apartment in center of the city.",
dailyPrice: 23
}]
}
}
render(){
const {rentals} = this.state;
return(
<div className="card-list">
<div className="container">
<h1 className="page-title">Your Home All Around the World</h1>
<div className="row">
{
rentals.map((rental)=>{
return(
<div key={rental._id} className="col-md-3">
<div className="card bwm-card">
<img
className="card-img-top"
src={rental.image}
alt={rental.title} />
<div className="card-body">
<h6 className="card-subtitle mb-0 text-muted">
{rental.shared} {rental.category} {rental.city}
</h6>
<h5 className="card-title big-font">
{rental.title}
</h5>
<p className="card-text">
${rental.dailyPrice} per Night ยท Free Cancelation
</p>
</div>
</div>
</div>
)
})
}
</div>
</div>
</div>
)
}
}
export default RentalHome;
Try this:
class First extends React.Component {
constructor (props){
super(props);
}
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>;
return (
<div>
{listItems}
</div>
);
}
}

Resources