I'm having some trouble rendering components for each instance of an item in an object.
While I'm able to log the individual titles of each item, the return function doesn't return anything, regardless of which component I try to return. There are no errors, apparently.
Is there perhaps a better way of returning components according to each item in an object?
Any help would be greatly appreciated! :)
import React, { Component } from 'react';
export default class Wrapper extends Component {
const obj = () => ({
"one": {
"title": "one",
"description": "foo",
},
"two": {
"title": "two",
"description": "bar",
},
});
renderSingleItem(instance) {
console.log(instance); // THIS WORKS JUST FINE!
return ( // THIS DOESN'T WORK?!
<h2 key={instance.title}>
{instance.description}
</h2>
);
}
renderAllItems(data) {
Object.entries(data).forEach(([key, instance]) => {
return this.renderSingleItem(instance);
});
}
render() {
return (
<div>
{this.renderAllItems(this.obj)}
</div>
);
}
}
<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>
I've also attempted the following method, which actually renders a component, but only for the first item in the object.
import React, { Component } from 'react';
export default class Wrapper extends Component {
const obj = () => ({
"one": {
"title": "one",
"description": "foo",
},
"two": {
"title": "two",
"description": "bar",
},
});
renderSingleItem(instance) {
console.log(instance);
return (
<h2 key={instance.title}>
{instance.description}
</h2>
);
}
renderAllItems(data) {
for (var key in data) {
if (data.hasOwnProperty(key)) {
var instance = data[key];
for (var prop in instance) {
if (instance.hasOwnProperty(prop)) {
return (this.renderSingleItem(instance));
}
}
}
}
}
render() {
return (
<div>
{this.renderAllItems(this.obj)}
</div>
);
}
}
<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>
FYI, in my project, I'm importing a JSON object.
You have 2 issues in this function.
renderAllItems(data) {
Object.entries(data).forEach(([key, instance]) => {
return this.renderSingleItem(instance);
});
}
You need to add another return before Object.keys and you should be using .map and not .forEach since forEach is void, meaning it wont return anything.
The code should look like this.
renderAllItems(data) {
return Object.entries(data).map(([key, instance]) => {
return this.renderSingleItem(instance);
});
}
This solution worked great for me:
import React from 'react';
import { render } from 'react-dom';
export default class Wrapper extends React.Component {
constructor(props) {
super(props)
this.obj = {
"one": {
"title": "one",
"description": "foo",
},
"two": {
"title": "two",
"description": "bar",
},
};
}
renderSingleItem(instance, k) {
console.log(instance); // THIS WORKS JUST FINE!
return (<h2 key={k} children={instance.description} />);
}
/*
* Not necessary
renderAllItems(data) {
Object.entries(data).forEach(([key, instance]) => {
return this.renderSingleItem(instance);
});
}*/
render() {
return (
<div>
{Object.keys(this.obj).map((k) => {
return this.renderSingleItem(this.obj[k], k);
})}
</div>
);
}
}
// I'll leave this for you
// render(<Wrapper />, document.getElementById('root'));
Related
Hello everyone I have function like that.When I tried to call my datas I can just reach to first index of each array.For example I have 5 different pictures of playstation but on my web page I just see 1 picture. How can I fix it?Is something missing in function or should change to function ?
in advance thank you
import React from 'react'
import { gql, useQuery } from '#apollo/client';
import { Image } from 'antd';
import { useState } from 'react';
const GET_TECH = gql`
query AllItem{
categories{
name
products{
name
brand
attributes{
name
id
}
gallery
category
prices{
currency{
label
symbol
}
amount
}
inStock
description
}
}
}
`;
function Tech() {
const { loading, error, data } = useQuery(GET_TECH);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;
console.log(data);
return (
<div className='pageLayout'>
{
(data.categories).map((item,index) => {
//const {name,brand,description,gallery,category} = item;
{
return (item.products).map((itemPrdct,subIndex) => {
const {name,brand,description,gallery,category} = itemPrdct;
if(category === "tech"){
console.log(name)
return(
<div className="tech" key = {subIndex}>
<p className='nametag' >{brand}</p>
<Image width={200} src={gallery} className='gallery'/>
</div>
)
}
})
}
})
}
</div>
)
}
export default Tech
> //Graphql structure
{
"data": {
"categories": [
{
"name": "all",
"products": [
{
"name": "Nike Air Huarache Le",
"brand": "Nike x Stussy",
"attributes": [
{
"name": "Size",
"id": "Size"
}
],
"gallery": [
"https://cdn.shopify.com/s/files/1/0087/6193/3920/products/DD1381200_DEOA_2_720x.jpg?v=1612816087",
"https://cdn.shopify.com/s/files/1/0087/6193/3920/products/DD1381200_DEOA_1_720x.jpg?v=1612816087",
"https://cdn.shopify.com/s/files/1/0087/6193/3920/products/DD1381200_DEOA_3_720x.jpg?v=1612816087",
"https://cdn.shopify.com/s/files/1/0087/6193/3920/products/DD1381200_DEOA_5_720x.jpg?v=1612816087",
"https://cdn.shopify.com/s/files/1/0087/6193/3920/products/DD1381200_DEOA_4_720x.jpg?v=1612816087"
],
console.log
I was thinking if gallery is an array then it should use map on arrays
const {name,brand,description,gallery,category} = itemPrdct;
if(category === "tech"){
console.log(name)
return(
<div className="tech" key = {subIndex}> // key can be `${idx}${subIndex}` if products are repeating
<p className='nametag' >{brand}</p>
gallery?.map((url, idx) => {
return (<Image key={idx} width={200} src={url} className='gallery'/>)
}
</div>
)
} // else { return (<EmptyElement /> } // consider returning empty element
})
// map through the image
gallery?.map((url, idx) => {
return (<Image key={idx} width={200} src={url} className='gallery'/>)
}
you can use useMemo to transform the response and filter out empty elements then map the items as needed
hope it works
I am new to React js and I am trying to fetch data from API and I am getting all data in this.state but while displaying in dropdown I am getting an above error. Please go through the code and let me know where I went wrong.
Json data:
{
"status":true,
"message":"Success",
"data":{
"id":37,
"pan_no":"12345",
"pan_name":"abhishek",
"pan_front_image":"C:\\fakepath\\download.jpg",
"customer_image":"C:\\fakepath\\download.jpg",
"document_type":"Driving License",
"document_front_image":"C:\\fakepath\\download.jpg",
"document_back_image":"C:\\fakepath\\download.jpg",
"bank_name":"ada",
"account_no":"12345",
"confirmed_acc_no":"12345",
"ifsc_code":"MITM2250451",
"account_holder_name":"fasfdas",
"phone_no":"1234567890",
"nick_name":"213123"
}
}
Code:
import React, { Component } from 'react';
class Home extends Component {
constructor() {
super();
this.state = {
data: [],
};
}
componentDidMount() {
fetch("http://127.0.0.1:8003/api/kyc/")
.then(results => results.json())
.then(data => this.setState({ data: data }));
// .catch(()=>this.setState({hasErrors:true}));
}
render() {
console.log(this.state.data);
return ( <div>
<div class = "ab-info-con" >
<h4> Menu </h4>
<select> {
this.state.data.map((obj) => { <
option value = { obj.id } > { obj.pan_no } </option>
})
} </select>
</div>
</div>
)
}
}
export default Home;
The error is being thrown because .map is an array method and you are calling it on an object. From the structure of your response and your code, I can guess that what you should do is this.
import React, {Component} from 'react';
class Home extends Component {
constructor(){
super();
this.state = {
id: '',
panNo: ''
};
}
componentDidMount() {
fetch("http://127.0.0.1:8003/api/kyc/")
.then(results=>results.json())
.then(data=>this.setState({ id: data.data.id, panNo: data.data.pan_no }));
// .catch(()=>this.setState({hasErrors:true}));
}
render(){
return (
<div>
<div class="ab-info-con">
<h4>Menu</h4>
<select>
{
<option value={this.state.id}>{this.state.panNo}</option>
}</select>
</div>
</div>
)
}
}
export default Home;
import React, { Component } from 'react';
class Home extends Component {
constructor() {
super();
this.state = {
data: [],
};
}
componentDidMount() {
fetch("http://127.0.0.1:8003/api/kyc/")
.then(results => results.json())
.then(data => this.setState({ data: data }));
// .catch(()=>this.setState({hasErrors:true}));
}
renderOptions = () => {
const { data } = this.state;
let options = [];
if (typeof data !== "undefined") {
if (Object.keys(data).length === 0) {
for (const property in data) {
options.push(<option value={property.id}>{property.pan_no}</option>)
}
}
}
return options;
}
render() {
console.log(this.state.data);
return (
<div>
<div class="ab-info-con">
<h4>Menu</h4>
<select>
{this.renderOptions()}
</select>
</div>
</div>
)
}
}
export default Home;
try this, i have added the empty check before looping the data.
Your example doesn't need mapping at all, as you are having only one record. To get the id and panNo you should use this.state.data.data.id and this.state.data.data.panNo.
If you would need to use map() on an object, I would suggest using Object.keys:
Instead of this:
<select> {
this.state.data.map((obj) => { <
option value = { obj.id } > { obj.pan_no } </option>
})
} </select>
Use this (doesn't make sense with this data structure, only to show the idea):
<select> {
Object.keys(this.state.data).map((obj) => { if(obj == 'data'){ <
option value = { this.state.data[obj].id } > { this.state.data[obj].pan_no } </option>
}})
} </select>
I'm trying to change the state of only one specific array item from the reviews array. How can this be done? This code doesn't seem to work:
this.setState({
reviews[2].current: true
});
Here's the full code:
import React, { Component } from "react";
import { render } from "react-dom";
const reviewsInit = [
{
name: "Peter Lahm",
current: null
},
{
name: "Simon Arnold",
current: null
},
{
name: "Claire Pullen",
current: null
}
];
class App extends Component {
constructor() {
super();
this.state = {
name: "React",
reviews: reviewsInit
};
}
change = () => {
this.setState({
reviews[2].current: true
});
};
render() {
return (
<div>
{console.log(this.state.reviews[2].current)}
<button onClick={this.change}>click me</button>
</div>
);
}
}
render(<App />, document.getElementById("root"));
Demo: https://stackblitz.com/edit/react-tbryf5
As you can probably tell I'm new to react! Thanks for any help here
For some context, React detects state change when reference of the state object changes. It does not track deep changes happening in array or the object.
Solution
We need to make another variable with same data (mostly destructuring). Change the value needed. And assign that to state again.
For Object
this.setState({...oldState, keyToChange: 'newValue'});
For Array
const temp = [...oldState];
temp[index] = 'newValue';
this.setState(temp);
Hope it helps.
It's common for an Array state to copy first then update one of its value
change = () => {
const result = [...this.state.reviews];
result[2].current = true;
this.setState({reviews: result});
};
import React, { Component } from "react";
import { render } from "react-dom";
const reviewsInit = [
{
name: "Peter Lahm",
current: null,
},
{
name: "Simon Arnold",
current: null,
},
{
name: "Claire Pullen",
current: null,
},
];
class App extends Component {
constructor() {
super();
this.state = {
name: "React",
reviews: reviewsInit,
};
}
change = () => {
const prevState = [...this.state.reviews];
prevState[2].current = true;
this.setState({
reviews: prevState,
});
};
render() {
return (
<div>
{console.log(this.state.reviews[2].current)}
<button onClick={this.change}>click me</button>
</div>
);
}
}
render(<App />, document.getElementById("root"));
i have a an array of data in a file named 'external-data.js' like this
``
export const mydata = [
{
name: "john",
age: 20,
man: true
},
{
name: "julia",
age: 22,
man: false
}
];
``
and then i import the data in my 'reactjs' app and i tried destructuring it like so
``
import React, {component} from 'react';
import { mydata } from 'external-data.js';
class HumanApp extends Component {
state = {
myNewData: [...mydata]
}
componentDidMount() {
this.changeData();
}
const changeData = () => {
myNewData.map(item => item.name = 'boyka');
console.log("state Data: "+myNewData[0].name);
console.log("original Data:"+Mydata[0].name);
}
render() {
return (
....
);
}
};
export default HumanApp;
``
and then i expected to get: " state Data: boyka" and "original Data: john" but it seems that my changeData function also changed the original array and i get "original Data: boyka"
state = {
myNewData: [
...mydata.map(data => { ...data })
]
}
There you go:
import React, { Component } from "react";
import { mydata } from "./external-data.js";
class App extends Component {
state = {
myNewData: [...mydata]
};
componentDidMount() {
this.changeData();
}
changeData = () => {
this.setState(
(prevState) => {
const myNewData = { ...prevState.myNewData };
this.state.myNewData.forEach((item) => {
item.name = "boyka";
});
return {
myNewData
};
},
() => {
console.log(this.state.myNewData);
}
);
};
render() {
return <div>Hii</div>;
}
}
export default App;
You cannot mutate the state directly!! You need to change the state using useState() like the example above.
I have this json in my react component as codeData
{
"type":"Simple count",
"codeCount": {
"lang": {
"java": 4,
"cpp":3,
"c":5
},
"ds": {
"array": 4,
"tree":5
}
}
}
In page I want to show above json in form of list as follows.
lang
*java(4)
*cpp(3)
*c(5)
ds
*array(4)
*tree(5)
For that I have to iterate through java object codeData.codeCount.But I am not able to figure out how to show key and value in loop.
class Showdata extends Component {
render() {
const {codeData} = this.props;
return (
<div>
for (let [key, value] of {codeData.codeCount}(myObj)) {
<ul>
</ul>
}
</div>
);
}
Check this:
let data = {
"type":"Simple count",
"codeCount": {
"lang": {
"java": 4,
"cpp":3,
"c":5
},
"ds": {
"array": 4,
"tree":5
}
}
}
class Showdata extends React.Component {
render() {
const {codeCount} = data;
return (
<div>
{Object.keys(codeCount).map(key=>{
return <ul>
{key}
{
Object.keys(codeCount[key]).map(el=> <li>{el} : {codeCount[key][el]}</li>)
}
</ul>
})}
</div>
);
}
}
ReactDOM.render(<Showdata/>, document.getElementById('app'))
<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='app'/>