Props is not updating in class component React - reactjs

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} />

Related

How to iterate data from array?

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} />;
})}
</>
);
}

how to add onClick function to array

I am trying to add onClick function to this array. So when i click on "How will i get cashback?",output
it must display the items(Page Page One,Two) image and when i click on "Page Page One", it must display "Subcontent"
stackblitz
export default class Chat extends React.Component {
constructor(props) {
super(props);
this.state = {
message: [
{
id: 1,
title: "How will i get cashback?",
items: [
{
id: 1,
title: "Page Page One",
items: [
{
id: 1,
title: 'SubContent'
}
],
},
{
id: 2,
title: "Two",
},
],
},
{
id: 2,
title: "Reschedule delivery",
items: [],
},
],
};
}
render() {
const { message } = this.state;
return (
<div>
<p className={styles.titleText}>AAAAAA</p>
<div className={styles.line} />
{message.map((m) => (
<div>
<div
className={styles.button}
>
{m.title}
<i
className={`fa fa-chevron-right`}
aria-hidden="true"
/>
</div>
<div className={styles.line} />
</div>
))}
</div>
);
}
}
Add this change to your code.
Basically what you are telling your program is "If I have items, then set the state to be these items, else do nothing"
<div className={`button`} onClick={() => m.items ? this.setState({ message: m.items }) : null}>
{m.title}
<i className={`fa fa-chevron-right`} aria-hidden="true" />
</div>

How update array in the state and show updated array with map() in reactjs

i create a state and make an array in it i succeeded to push in array and map them ,
but i cant show updated array in my view , how can i update state before show anything
my code is:
class App extends Component{
constructor(){
super()
this.state = [
{id:'1' , title : ''},
{id:'2' , title : ''},
{id:'3' , title : ''}
]
}
increment = (a) =>{
this.state.push({id : ReactDOM.findDOMNode(this.refs.id).value , title : ReactDOM.findDOMNode(this.refs.user).value})
}
render(){
return(
<div>
<input type="text" ref='id' placeholder='id'/>
<input type="text" ref='user' placeholder='user'/>
<button onClick={this.increment}>+</button>
<ul>{
this.state.map((item , id) =>
<li key={id}>
<h1>{item.title}</h1>
</li>)
}
</ul>
</div>
)
}
}
class App extends Component {
constructor() {
super();
this.state = {
todos: [
{ id: "1", title: "title 1" },
{ id: "2", title: "title 2" },
{ id: "3", title: " title 3" }
]
};
}
increment = a => {
const id = ReactDOM.findDOMNode(this.refs.id).value;
const title = ReactDOM.findDOMNode(this.refs.user).value;
this.setState(state => {
state.todos.push({ id, title });
return { todos: state.todos };
});
};
render() {
const { todos } = this.state;
console.log(todos);
return (
<div>
<input type="text" ref="id" placeholder="id" />
<input type="text" ref="user" placeholder="user" />
<button onClick={() => this.increment()}>+</button>
<ul>
{todos.map((item, id) => (
<li key={id}>
<h1>{item.title}</h1>
</li>
))}
</ul>
</div>
);
}
}
you've to use to push value to array.
this.setState(state => {
state.todos.push({ id, title });
return { todos: state.todos };
});
you can see the working examples here https://codesandbox.io/s/prod-wood-jj8rd

How to display nested array data in JSON in ReactJS?

I have problem to display nested array data that I retrieved from api call. The JSON data format is like:
[
{
pageNo: 1
TotalRecordsCount: 8000,
Items: [
{
id: 1,
subject: "ACCOUNTING",
campus: "campus A"
},
{
id: 1,
subject: "ACCOUNTING",
campus: "campus A"
},
...
}
]
Edit data format:
Items: [{subject: ACCOUNTING, CAMPUS: CAMPUS A}, {subject: ACCOUNTING, campus: CAMPUS A}...]
PageNo: 1
TotalRecordCount: 8000
in JSON format.
How to access subject, campus, etc. data in ReactJS? I got the error message: Objects are not valid as a React child (found: object with keys {courseItem}).
App.js
import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
constructor() {
super();
this.state ={
courses:[]
};
}
componentDidMount(){
axios.get('myURL')
.then(response=>{
this.setState({
courses:response.data
});
});
}
_getCourses(){
const data=this.state.courses;
const courseItem=data.map((course,index)=>(
<div>
Page No: course.ageNo <br />
<div className="courseItem"><ul>
Course: <li>ID:{course.id}
SUBJECT:{course.subject}
CAMPUS: {course.campus} </li>
</ul></div>
</div>
));
render() {
const courses= this._getCourses();
return (
<div className="App">
<div className="courseResults">
{courses}
</div>
</div>
);
}
}
export default App;
Thanks.
In componentDidMount you are currently setting courses to just response.data. And this is the outer array from your response. The courses array is the inner array. So, you need to set courses to response.data[0].Items. Perhaps you want to iterate over response.data array as well if you expect more than one entry there.
componentDidMount() {
axios.get('http://localhost:8080')
.then(response => {
this.setState({
courses: response.data[0].Items
});
});
}
In _getCourses you need to return the courseItems variable:
_getCourses() {
const data = this.state.courses;
const courseItems = data.map((course, index) => (
<div>
Page No: course.ageNo <br />
<div className="courseItem"><ul>
Course: <li>ID:{course.id}
SUBJECT:{course.subject}
CAMPUS: {course.campus} </li>
</ul></div>
</div>
));
return courseItems;
}
You have the render function inside of the _getCourses and it has to be on the same level, at the class level:
class App extends Component {
constructor() { ... }
componentDidMount() { ... }
_getCourses() { ... }
render() { ... }
}
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
constructor() {
super();
this.state = {
courses: [
{
pageNo: 1,
TotalRecordsCount: 8000,
Items: [
{
id: 1,
subject: "ACCOUNTING",
campus: "campus A"
},
{
id: 1,
subject: "ACCOUNTING",
campus: "campus A"
}
]
}
]
}
}
_getCourses() {
const data = this.state.courses.slice(0);
const courseItem = data.map((course, index) => (
<div>
Page No: course.ageNo <br />
<div className="courseItem">
<ul>
{course.Items.map((details, index) => (
<React.Fragment>
<li>
Course: ID:{details.id}
</li>
<li>
SUBJECT:{details.subject}
</li>
<li>
CAMPUS: {details.campus}
</li>
</React.Fragment>))}
</ul>
</div>
</div>
))
return courseItem;
}
render() {
return (
<div className="App">
<div className="courseResults">
{this._getCourses()}
</div>
</div>
);
}
}
render(<App />, document.getElementById('root'));
https://stackblitz.com/edit/react-mnh5ex?embed=1&file=index.js
You needed to return courseItem in the _getCourse function. Otherwise it will not render any html when you call the _getCourse in the render function.
You also need to acess Items, because Items contains the data you want to access.
{
id: 1,
subject: "ACCOUNTING",
campus: "campus A"
},
{
id: 1,
subject: "ACCOUNTING",
campus: "campus A"
}

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