how to print an array from an object in react? [duplicate] - javascript

This question already has answers here:
How to print array of object in react
(2 answers)
Closed 7 months ago.
const api = axios.create({
baseURL: 'https://iotserver-arha83.herokuapp.com/api/customers/'
})
class App extends Component {
state = {
courses:[]
}
constructor(){
super();
api.get('/').then(res =>{
this.setState({courses: res.data})
})
}
render(){return (
<div className="App">
<header className="App-header">
<table>
<tr><td>pk</td>{this.state.courses.map(course=><td>{course.pk}</td>)}</tr>
<tr><td>title</td>{this.state.courses.map(course=><td>{course.title}</td>)}</tr>
<tr><td>gateway</td>{this.state.courses.map(course=><td>{course.gateway}</td>)}</tr>
</table>
</header>
</div>
);}
}
export default App;
[
{
"pk": 1,
"title": "first",
"gateways": [1]
}, {
"pk": 2,
"title": "second",
"gateways": [2]
}, {
"pk": 5,
"title": "test",
"gateways": []
}, {
"pk": 6,
"title": "test",
"gateways": []
}
]
this is my code and I want to print every item on my website
but I can't print gateways because it's an array
I tried to change the gateway into string so it might be printed but didn't work
any ideas...?
note: this code should print every thing on the upper list

You need to iterate over the array only once using the map() method and render a tr for each element.
<table>
<tr>
<th>pk</th>
<th>title</th>
<th>gateway</th>
</tr>
{courses.map((course) => (
<tr key={course.pk}>
<td>{course.pk}</td>
<td>{course.title}</td>
<td>{course.gateways.join(",")}</td>
</tr>
))}
</table>
Property gateways is also an array which you can map too, however since you only want to render values you can use join(",") method instead.
On a side note, it's better to start using functional components.

Related

Avoid duplication in React array map function [duplicate]

This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 8 months ago.
I am fetching some data in form of strings , and I would like to avoid any duplication when I map this array .
This is how I am using this function in React :
<Flex >
{allPrismicCollection.nodes.map((collection)=>
(
<Navbar>
<NavTitle>{collection.data.collection.text}</NavTitle>
<NavbarFlex>
{collection.data.slides.map((coll)=>
<>
{coll.slide.document.data.blogs.map((s)=>
<>
{s.blog.document.data.tags.map((t)=>
(
<NavLink><Link to='#'>{t.tag}</Link></NavLink>
)
)}
</>
)}
</>
)}
</NavbarFlex>
</Navbar>
)
)}
</Flex>
This is the JSON format of the array , it contains multiple blog fields and each field has various tags fields .
"blogs": [
{
"blog": {
"document": {
"id": "4a007c39-2053-5c5e-8f38-56ba8c3aced5",
"data": {
"tags": [
{
"tag": "Entertainment"
},
{
"tag": "Happiness"
},
{
"tag": "Philosophy"
}
]
}
}
}
},
{
"blog": {
"document": {
"id": "9e78be5c-08e7-5684-adaa-b788cb4020b7",
"data": {
"tags": [
{
"tag": "Life"
},
{
"tag": "Vacation"
},
{
"tag": "Drama"
}
]
}
}
}
}
]
}
}
}
},
When consoling s.blog.document.data.tags I get multiple arrays , I need to wrap them in a single array based on the collection name !
the t.tag will return some duplicated values and I don't want it , how can I solve this please ?
You can use a package named lodash installable via npm or yarn. Then import the uniq function to use.
E.g.
import { uniq } from 'lodash'
Your code should then look like this
{uniq(s.blog.document.data.tags).map((t)=>
(
<NavLink><Link to='#'>{t.tag}</Link></NavLink>
)
)}
If t is an object, like in your case then you will need to use uniqBy function instead.
import { uniqBy } from "lodash"
Then your code should be
{uniqBy(s.blog.document.data.tags, 'tag').map((t)=>
(
<NavLink><Link to='#'>{t.tag}</Link></NavLink>
)
)}

React gives me the error TypeError: XXX.map is not a function [duplicate]

This question already has answers here:
React JS - Uncaught TypeError: this.props.data.map is not a function
(17 answers)
Closed 3 years ago.
I am new to React and it gives me the error below, which I cannot resolve. I searched in the internet, a lot of people faced the same problem but "map" is a built in function, why does it say that it is not a function?
import React, { Component } from 'react';
export class UrunlerComponentList extends Component {
displayName = UrunlerComponentList.name
constructor(props) {
super(props);
this.state = { urunler_: [], loading: true };
fetch('http://localhost:55992/api/search/arama?q=&PageIndex=1')
.then(response => response.json())
.then(data => {
this.setState({ urunler_: data, loading: false });
});
}
static renderUrunlerTable(urunler_) {
return (
<table className='table'>
<thead>
<tr>
<th>SKU</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{urunler_.map(urun =>
<tr>
<td>{urun.SKU}</td>
<td>{urun.Name}</td>
</tr>
)}
</tbody>
</table>
);
}
render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: UrunlerComponentList.renderUrunlerTable(this.state.urunler_);
return (
<div>
<h1>Urunler</h1>
<p>This component demonstrates fetching data from the server.</p>
{contents}
</div>
);
}
}
The webapi I am calling returns the value below...
{
"$id": "1",
"RecordCount": 879,
"products": [
{
"$id": "2",
"Id": 17034,
"BrandId": 3,
"SKU": "7436B003-1082",
"Name": "xxxxxxxx",
"InStock": 1,
"URL": "xxxxxxxxxx",
"Description": "xxxxxxxxxxxxxxxxx",
"Price": 9.90,
"DiscountRatio": 0.00,
"TechnicalDetail": "xxxxxxxxxxxxxxxxx",
"ImageUrl": "7436Bxxxxxx.jpg",
"Active": true,
"CreatedDate": "2019-07-20T11:36:35.333",
"Brand": null,
"CartDetails": [],
"OrderDetails": [],
"ProductCategoryRelations": [],
"ProductColorRelations": [],
"ProductFileRelations": [],
"ProductPropertyRelations": []
},
This should fix it. Data itself is an object not an array. You want to assign products I guess.
...
.then(({products}) => this.setState({ urunler_: products, loading: false }))
...
Make sure the value returned from your fetch call is an array and is not undefined since you are setting that value to your state.
fetch('http://localhost:55992/api/search/arama?q=&PageIndex=1')
.then(response => response.json())
.then(data => {
// make sure 'data' is an array
this.setState({ urunler_: data, loading: false });
});
<tbody>
{typeof urunler_ !== 'undefined' && urunler_.length > 0 ?
(urunler_.map(urun =>
<tr>
<td>{urun.SKU}</td>
<td>{urun.Name}</td>
</tr>
)):(<tr><</tr>)}
</tbody>

Properly filter an array inside other array in reactjs

Hello I am trying react for the first time and I am having some trouble with my filter function.
Here's the code:
So this is my render method in my component:
const categoryFilter = this.state.appItems.filter(item =>
item.categories.filter(str => {
return str.includes(active);
})
);
const appList = categoryFilter.map(appItem => (
<AppItem appItem={appItem} key={appItem.id}></AppItem>
));
return (
<React.Fragment>
<div className="flex-container">
<NavCategories
categories={this.state.categories}
onClick={this.handleClick}
active={active}
/>
<section className="apps-list">
<header>
<input type="text" placeholder="Search by App" />
</header>
<ul>{appList}</ul>
</section>
</div>
</React.Fragment>
);
this.state.appItems is an array coming from a json file, here's a snippet:
[ {
"id": "12312",
"name": "Test",
"description": "test.",
"categories": ["Voice", "Delivery", "Optimization"],
"subscriptions": [
{
"name": "Trial",
"price": 0
},
{
"name": "Professional",
"price": 3500
}
]
},]
Active is a string to manage active class items on another component.
Everything renders correctly, but it is never filtered even though the active state is changing everytime.
I have tried multiple ways, but this Filter method is getting me confused a lot because I want to filter an array thats inside another array and want to filter the whole AppItem array.
If anyone could explain/give me some tips I would love it. Thanks in advance :)
Array.filter() returns a new array with the filtered elements in it. So your inner filter will always return an array of at least zero elements, which evaluates to a truthy value, and your outer filter will just include every element in the original array.
Just switch your inner filter to be an Array.includes() instead, which will return true or false.
const categoryFilter = this.state.appItems.filter(item =>
item.categories.includes(active)
);

How to separate out a JSON Object for a reusable React table component

I have an object, as seen below:
{
"id": 1,
"name": "Dan",
"icon": "",
"stat_1": 1.2,
"stat_2": 2.5,
"stat_3": 4.1,
"stat_4": 1,
"stat_5": 12,
"critical_hit": true,
"g_combo": [],
"a_combo": [],
"t_combo": [],
}
My goal is to be able to loop over this object (exclude the arrays) and create a table that looks like this:
+---------------------------+
| Character Stats for Dan |
+---------------------------+
| ID | 1 |
+---------+-----------------+
| NAME | Dan |
+---------+-----------------+
| ICON | {icon img} |
+---------+-----------------+
...etc..
Basically, create a table that uses the Object Key as the left column, and the Object Value for the right.
So far, this is what I have tried, but keep running into errors with React:
export default function SpecSheet(props) {
const character = props.CharacterData;
const characterInfo = Object.entries(character);
return (
characterInfo.map((item, index)=> (
<tr key={index}>
<td>{item[0]}</td>
<td>{item[1]}</td>
</tr>
});
))
)
and then I will call it on my file like this:
<SpecSheet CharacterData={data} />
{data} is the reference to my JSON file.
My problem:
This seems to generate exactly what i'm looking for in the console, except for the fact that it doesn't filter the arrays out, and the Table doesn't seem to generate on the page. The only error I;m getting is
Warning: Each child in a list should have a unique "key" prop., but I'm providing an index on my tr element.
Any ideas how I could solve this?
What if you tried something like this:
const data = {
"id": 1,
"name": "Dan",
"icon": "",
"stat_1": 1.2,
"stat_2": 2.5,
"stat_3": 4.1,
"stat_4": 1,
"stat_5": 12,
"critical_hit": true,
"g_combo": [],
"a_combo": [],
"t_combo": [],
};
function SpecSheet(props) {
const character = props.CharacterData;
const characterInfo =
Object.entries(character)
.filter(([key,val]) => !Array.isArray(val));
return (
characterInfo.map((item, index) => (
<tr key={`${character.id}-${item[0]}`}>
<td>{item[0]}</td>
<td>{item[1]}</td>
</tr>
)
)
);
}
ReactDOM.render(<SpecSheet CharacterData={data} />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
This will filter out any values that are an array, and uses the character's (hopefully) unique id with the property as the key for each <tr/<}>
In your lowest code block, you have an extra closed curly brace that doesn't belong.
Try using Object.keys(danObj). This will create an array of the keys in your Object. So assuming I get to renamek your object to danObj, you can do something like this:
const tableRows = Object.keys(danObj)
// Don't run this code on your arrays
.filter(obj => !Array.isArray(danObj[obj]))
.map(stat => (
<tr key={stat}>
<td>{stat}</td>
<td>{danObj[stat]}</td>
</tr>
)
Info on Object.keys: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

How to populate bootstrap grids with JSON data obtained from fetch() in Reactjs?

I want to populate JSON data into bootstrap grid system.
JSON response:
{
"_id": "5a63051735aaddd30d1d89f8",
"id": 45,
"season": 2008,
"city": "Bangalore",
"team1": "Royal Challengers Bangalore",
"team2": "Delhi Daredevils",
"toss_winner": "Delhi Daredevils",
"toss_decision": "field",
"result": "normal",
"dl_applied": 0,
"winner": "Delhi Daredevils",
"win_by_runs": 0,
"win_by_wickets": 5,
"player_of_match": "SP Goswami",
"venue": "M Chinnaswamy Stadium",
"umpire1": "SJ Davis",
"umpire2": "GA Pratapkumar",
"umpire3": ""
}
The JSON response returns around 577 JSON objects now I want to populate above JSON data into bootstrap grid system.
main.js
class Main extends Component {
constructor(){
super();
this.state={
matches: []
};
}
componentDidMount(){
fetch('api/matches')
.then(res => res.json())
.then(matches => this.setState({matches}, () => console.log('Matches fetched...', matches)));
}
render() {
return (
<div>
<div class="row">
<div class="col-lg-4" styles="background-color:lavender;">{this.state.matches[0].season}</div>
<div class="col-lg-4" styles="background-color:lavenderblush;">{this.state.matches[5].season}</div>
<div class="col-lg-4" styles="background-color:lavender;">{this.state.matches[8].season}</div>
</div>
</div>
);
}
}
In above code I am trying to display matches[0].season matches[5].season
matches[8].season but shows error see screenshot below.
Just need to wait for setState() to be called, which would in turn populate the matches array. Remember that because you're using componentDidMount, as well as making an asynchronous call to fetch data, the component will have already rendered with this.state.matches set to an empty array.
Here's a quick CodePen.
This may help as well - Where to Fetch Data
We can populate bootstrap grids by using fetch() see below code:
componentDidMount() {
fetch('api/matches')
.then(res => res.json()) // It resolves the promise with a JSON object
.then(res => {
console.log(res)
this.setState({
matches: res,
})
})
}
Also in render function add conditional statement:
render() {
if (this.state.matches.length === 0) {
return <div>>Loading...</div>
}
return (
<div>
<div class="row">
<div class="col-lg-4" styles="background-color:lavender;">{this.state.matches[0].season}</div>
<div class="col-lg-4" styles="background-color:lavenderblush;">{this.state.matches[5].season}</div>
<div class="col-lg-4" styles="background-color:lavender;">{this.state.matches[8].season}</div>
</div>
</div>
)
}

Categories