How to make correct loop of JSON in React - javascript

I've got a problem with making a correct loop in React. I want to fetch data from JSON to don't repeat components. I tried to make two loops and then two maps, but everything was in bad order. The other problem is that "description" is also an array that's why I'm not able to deal with it
JSON:
{
"oswiecim": [
{
"header": "Oświęcim Zasole",
"description": [
"Rejon ulic św Maksymiliana Kolbego",
"i Stanisławy Leszczyńskiej"
]
},
{
"header": "Oświęcim Zasole",
"description": [
"Rejon ulic Więźniów Oświęcimia",
"Obozowej, Polnej i Legionów"
]
},
{
"header": "Stare Miasto",
"description": [
"Rejon Rynku i Placu ks. Jana Skarbka oraz ",
"ulic Zamkowej i Władysława Jagiełły"
]
},
{
"header": "Stare Miasto",
"description": [
"Cmentarz Parafialny oraz rejon",
"ul. Wysokie Brzegi."
]
},
{
"header": "Osiedle Chemików",
"description": [
"Największa pod względem liczby ludności",
"dzielnica Oświęcimia"
]
}
]
}
React:
import '../../styles/selection/Selection.scss'
import { useEffect, useState } from 'react';
const Selection = () => {
const [data, setData] = useState({})
const getData = async () => {
await fetch('https://jsoneditoronline.org/#left=cloud.b95a27020e1c45e9b3a7c95a74fc5d49', {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(res => res.json())
.then(data => {
setData(data)
})
}
useEffect(() => {
getData()
}, [])
const headers = []
const descriptions = []
for (const item of data.oswiecim) {
headers.push(item.header)
descriptions.push(item.description)
}
return (
<div className="selection">
{headers.map(item => (
<h1>{item}</h1>
))}
{descriptions.map(item => (
item.map(elem => (
<p>{elem}</p>
))
))}
</div>
);
}
export default Selection;
The result should look like this:

You don't need to separate header and description in two different variables.
So try something like this:-
return (
<div className="selection">
{data.oswiecim?.map((item) => (
<>
<h1>{item.header}</h1>
{item.description?.map((description) => (
<p>{description}</p>
))}
</>
))}
</div>
);
Live demo

Replace the setData(data); with following. It will just give the array you need to iterate,
setData(data.oswiecim);
Remove the following code,
const headers = []
const descriptions = []
for (const item of data.oswiecim) {
headers.push(item.header)
descriptions.push(item.description)
}
Replace return statement with following,
<div className="selection">
{data &&
data.map(item => (
<>
<div>{item.header}</div>
{item.description &&
item.description.map(descriptionItem => <p>{descriptionItem}</p>)}
</>
))}
</div>

Related

How to run nested React map function?

I have a JSON I need to fetch data & display in UI but not able to do due to nested.
JSON data:
data =[
{
"First Row": {
"info": 274.176,
}
},
{
"Second Row": {
"info": 139.536,
}
}
]
My Code:
{data
? data.map((val, i) =>
val[i].map((val2) => {
<>
<div>{val2.info}</div>
</>;
})
)
: ""}
Use Object.values() to get an array of all the values, then use [0] to get the first object where you can acces the info as desired:
data.map((val, i) => Object.values(val)[0].info)
[
274.176,
139.536
]
const data = [
{ "First Row": { "info": 274.176, } },
{ "Second Row": { "info": 139.536, } }
];
const r = data.map((val, i) => Object.values(val)[0].info);
console.log(r)
If you want to display only the info value, you can do the following. It loops through the data array. And for each item, gets the value of the first key. (assuming each item only has one key)
const DataDisplay = ({ data }) => {
return (
<div>
{data.map((item, index) => {
return (
<div key={index}>
<h3>{Object.keys(item)[0]}</h3>
<div>{Object.values(item)[0].info}</div>
</div>
);
})}
</div>
);
};

in map function why I cannot reach all elements?

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

How to access more complex nested data JSON in REACT

I'm trying to render a row of 10 books and a row of 10 movies from my component which would look like rows in netflix to give you an idea. I've shortened the json bellow. I'm able to fetch and access my data and save it in useState of the component. Although I'm not able to render. Lack of experience. I've paste result in both console.log bellow react component. Help would be welcome please!!!
JSON file
[
{
"id": 1,
"rowTitle": "Books",
"row": [
{
"id": 1,
"title": "Book1",
"desc": "Book1 description",
"url": "images/books/Book1.jpeg"
},
{
"id": 2,
"title": "Book2",
"desc": "Book2 description",
"url": "images/books/Book2.jpeg"
},
]
},
{
"id": 2,
"rowTitle": "Movies",
"row": [
{
"id": 1,
"title": "movie1",
"desc": "movie1 description",
"url": "images/movies/movie1.jpeg"
},
{
"id": 2,
"title": "movie2",
"desc": "movie2 description",
"url": "images/movies/movie2.jpeg"
},
]
}
]
React component
import { Link } from 'react-router-dom';
import { Caroussel, RowSlider, SliderContainer, Title } from './Home.styled';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
const Home = () => {
const [data, setData] = useState([]);
const getData = () => {
fetch('data/projects.json', {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
})
.then((response) => {
console.log(response);
return response.json();
})
.then((myJson) => {
console.log(myJson);
setData(myJson);
});
};
useEffect(() => {
getData();
}, []);
const settings = {
dots: false,
infinite: false,
speed: 1000,
slidesToShow: 2,
slidesToScroll: 2,
// lazyLoad: 'progressive',
};
return (
<>
<RowSlider>
<Title>
{data.map((obj) => {
console.log(obj);
// RESULT -> Object { id: 1, rowTitle: "Books", row: (10) […] }
return <h1>{obj.rowTitle}</h1>;
// -> RESULT but this render at the same time both titles (BOOKS and MOVIES), and I need to render BOOKS title first then its books row before rendering next row, MOVIES title and its movies..
})}
</Title>
<SliderContainer>
<Caroussel {...settings}>
{data &&
data.map((slide) => {
console.log(slide);
// RESULT -> Warning: Each child in a list should have a unique "key" prop. ** BUT not event sure event if they was an it would still be working
return (
<div key={slide.id}>
<div className="slick-slide">
<img
className="slick-slide-image"
alt={slide.title}
src={slide.url}
/>
<h2 className="slick-slide-title">{slide.title}</h2>
</div>
<Link to="/stations">
<div className="slick-slide-filter"> </div>
</Link>
</div>
);
})}
</Caroussel>
</SliderContainer>
</RowSlider>
</>
);
};
// {/* <label className="slick-slide-label">{slide.label}</label> */}
export default Home;
Your data is an array of objects so you a) need to iterate (map) over them, and then b) map over the row array inside those objects to build the HTML.
function Example({ data }) {
function getJSX(data) {
// `map` over the array and for each object
// return the rowTitle, and also `map` over
// each object in `row` and return some markup
return data.map(obj => {
return (
<div key={obj.id}>
<h4>{obj.rowTitle}</h4>
{obj.row.map(row => {
return <div>{row.title}: {row.desc}</div>;
})}
</div>
);
});
}
return (
<div>
{getJSX(data)}
</div>
);
};
const data=[{id:1,rowTitle:"Books",row:[{id:1,title:"Book1",desc:"Book1 description",url:"images/books/Book1.jpeg"},{id:2,title:"Book2",desc:"Book2 description",url:"images/books/Book2.jpeg"}]},{id:2,rowTitle:"Movies",row:[{id:1,title:"movie1",desc:"movie1 description",url:"images/movies/movie1.jpeg"},{id:2,title:"movie2",desc:"movie2 description",url:"images/movies/movie2.jpeg"}]}];
ReactDOM.render(
<Example data={data} />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

How can i see my array on my component ? / React / Javascript

I have a element like :
const DropdownElements = [
{
key: 1,
title: "Şehir",
placeholder: "Şehir Seçiniz",
apiUrl: "https://api.npoint.io/995de746afde6410e3bd",
type: "city",
selecteditem: "",
data : [],
},
{
key: 2,
title: "İlçe",
placeholder: "İlçe Seçiniz",
apiUrl: "https://api.npoint.io/fc801dbd3fc23c2c1679", // its my apis. They hold datas from json
type: "district",
selecteditem: "",
data : [],
},
]
I fetching that url in App in useEffect.
const App = () => {
useEffect(() => {
DropdownElements.map((x) => {
fetch(x.apiUrl)
.then((z) => z.json())
.then((vb) => {
x.data=vb // If i write x.data.push(vb) i can see it on my component but its not giving pure array.
console.log(x.data) // I can see my datas perfectly. I trying fill my data.
});
});
}, []);
And i setting it like that :
<Space>
{DropdownElements.map((x) => {
return (
<PickerCompanent
showSearch
selecteditem={idhold}
key={x.key}
placeholder={x.placeholder}
type={x.type}
datasource={x.data} // I gave my datasource x.data that i filled .
onFocus={onFocus}
onChange={z=>onChange(z)}
onFocus={onFocus}
onSearch={onSearch}
></PickerCompanent>
);
})}
</Space>
But in my component when i try write like console.log(props) my datasource is empty array. How can i see my datas on my component ? I need set my array to a state in my component.
It seems like you aren't using any kind of state in your code.
const App = () => {
const [myData, setMyData] = useState();
useEffect(() => {
DropdownElements.map((x) => {
fetch(x.apiUrl)
.then((z) => z.json())
.then((vb) => {
x.data=vb // If i write x.data.push(vb) i can see it on my component but its not giving pure array.
console.log(x.data) // I can see my datas perfectly. I trying fill my data.
// in here you'll want to be adding your data to some state
// e.g.
setMyData(x.data);
});
});
}, []);
Then within your component, use that state:
datasource={myData}
Your object is updating but not view. To achieve this you need have a component state, to which we can update and trigger return again to update view.
const App = () => {
const [myData, setMyData] = useState(DropdownElements);
useEffect(() => {
myData.map((x, i) => {
fetch(x.apiUrl)
.then((z) => z.json())
.then((result) => {
myData[i].data = result;
setMyData(myData);
});
});
}, []);
return (
<Space>
{myData.map((x) => {
return (
<PickerCompanent
showSearch
selecteditem={idhold}
key={x.key}
placeholder={x.placeholder}
type={x.type}
datasource={x.data} // I gave my datasource x.data that i filled .
onFocus={onFocus}
onChange={z=>onChange(z)}
onFocus={onFocus}
onSearch={onSearch}
></PickerCompanent>
);
})}
</Space>
);

How to write 2 fetch method for contact API and Message API in reactjs?

I'm new to reactjs. I could map the data from json API. My objective is when we save a number in contactlist, it should show the name in message list also. I want to create 2 fetch data i.e., messageData, ContactData that should compare the Phone numbers of message API and COntact API. If Phone number is same in contact API and Message API then it should return name otherwise it should return only phone number.
Contact json data would be like
[
{
"id": 1,
"name": "ABC",
"phone": "+91 789654123",
"email": "abcyz#gmail.com"
},
{
"id": 2,
"name": "DEF",
"phone": "+91 123456987",
"email": "defvu#gmail.com"
}
]
Contact Component:
import React, { Component } from "react";
import { Grid, Header, Button, Icon } from "semantic-ui-react";
import { Link } from 'react-router-dom'
class ComponentList extends Component {
state = {
peopleData: []
};
componentDidMount() {
fetch('./people.json')
.then(response => response.json())
.then(data => this.setState({ peopleData: data }));
}
pnum(num) {
return num.replace(/^\D/g, "");
}
render() {
const {peopleData} = this.state;
return(
<div>
{ peopleData.map(people =>
<Grid>
<Grid.Row key={people.id}>
<Grid.Column>
<Header>{people.name}</Header>
<span>{people.phone}</span>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Button trigger={<Link to={`/displayChat/${this.pnum(people.phone)}`}>
<Icon name='comment alternate outline' color='teal' /></Link>}/>
</Grid.Row>
</Grid>
)}
</div>
);
}
}
export default ComponentList;
Message API:
[
{
"id": 1,
"phone": "+91 789654123",
"message": "Hello everyone",
"isrespond": true,
},
{
"id": 2,
"phone": "+91 123456987",
"message": "hi",
"isrespond": false,
}
]
DisplayChat component:
fetchChat() {
const { phone } = this.props.match.params ;
fetch(`api/conversation/${phone}`)
.then(response => response.json())
.then(data => this.setState({ messageList: data})
);
}
render(){
const {messageList} = this.state;
const { phone } = this.props.match.params ;
return(
<div>
<ViewHeader phone={this.props.match.params}/>
<Container className="viewMessage ">
{messageList.map(data =>
<Grid>
<Grid.Row key={data.id}>
<p>{data.message}</p>
</Grid.Column>
</Grid.Row>
</Grid>
)}
</Container>
<TypeHere phone={this.props.match.params}/>
</div>
);
}
}
Can anyone help me in this?
const URL1= "contactApi"
const URL2= "messageApi"
I have used promise.all along with fetch to resolve both the endpoints
Promise.all([
fetch(URL1),
fetch(URL2),
]).then(responses => responses
).then(responses => Promise.all(responses.map(r => r.json())))
.then(data=>writeLogic(data));
function writeLogic(data){
let nameOrPhone;
const contactApiData = data[0]
const messageApiData = data[1]
let isPresent
for(let m of messageApiData){
isPresent=false
for(let c of contactApiData){
if(m.phone === c.phone){
isPresent=true
nameOrPhone.push(c.name)
}
}
if(!isPresent){
nameOrPhone.push(m.phone)
}
}
//update your state here if you are using React
//this.setState({nameOrPhone})
console.log(nameOrPhone)
}
data will contain result of both the endpoint in an array.
you can use the data and write your logic on top of it.
Ref: https://javascript.info/promise-api

Categories

Resources