Reputation: 119
I am trying to create a new dynamic button for every title by reading the contents of the json file stored in the local directory.
JSON File
[
{
"page" : "Page1" ,
"imptopics":[
{
"title" : "Btn1",
"url" : "https:link/"
},
{
"title" : "Btn2",
"url" : "http:link/"
},
{
"title" : "Btn3",
"url" :"http:link"
},
{
"title" : "Btn4",
"url" : "http:link"
}
]
}
]
This is my react component, I am using fetch to read the contents of json file,
import React from 'react'
import { useState , useEffect } from 'react'
import { Button } from 'antd'
function ImportantTopics() {
const [data,setData] = useState([]);
const getData = () =>{
fetch('popularlinksdata.json'
,{
headers :{
'Content-Type': 'application/json',
'Accept' : 'application/json'
}
}
)
.then(function(response){
return response.json();
})
.then(function(myJson){
console.log(myJson)
setData(myJson)
});
}
useEffect(() => {
getData()
}, [])
return (
<div className="grid grid-cols-2 gap-6">
{
data && data.length > 0 && data.map((topic) => {
topic.imptopics.forEach(element => {
console.log(element.title);
<Button className="sprtLinksButton">{element.title}</Button>
})
})
}
</div>
)
}
export default ImportantTopics;
But the button is not being rendered, It is being displayed in the console. What can I be missing?
Upvotes: 0
Views: 55
Reputation:
The JSON content is actually an array and we don't know how many elements there are. If you want to render all the imtopics
appearing in the JSON content, you can merge the imtopics
into one.
import React from 'react';
import { useState, useEffect } from 'react';
import { Button } from 'antd';
function ImportantTopics() {
const [data,setData] = useState([]);
const getData = () => {
fetch('popularlinksdata.json', {
headers :{
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(response => response.json())
.then(function(myJson) {
const imptopics = myJson.reduce((merged, item) => [...merged, ...item.imptopics], []);
// we will have all the imtopics merged into `imptopics`
setData(imptopics);
});
};
useEffect(() => {
getData()
}, []);
return (
<div className="grid grid-cols-2 gap-6">
{
data && data.length > 0 && data.map((topic, index) => (<Button key={index} className="sprtLinksButton">{topic.title}</Button>))
}
</div>
);
}
export default ImportantTopics;
Upvotes: 2
Reputation: 1701
forEach
doesn't return anything whereas map
returns an array. So you can either change the forEach to map or push the elements needs to be rendered to a variable and render that variable. I'd recommend the first option.
Example:
import React from 'react'
import { useState , useEffect } from 'react'
import { Button } from 'antd'
function ImportantTopics() {
const [data,setData] = useState([]);
const getData = () =>{
fetch('popularlinksdata.json'
,{
headers :{
'Content-Type': 'application/json',
'Accept' : 'application/json'
}
}
)
.then(function(response){
return response.json();
})
.then(function(myJson){
console.log(myJson)
setData(myJson)
});
}
useEffect(() => {
getData()
}, [])
return (
<div className="grid grid-cols-2 gap-6">
{
data && data.length > 0 && data.map((topic) => {
topic.imptopics.map((element, imdex) => (
<Button key={index} className="sprtLinksButton">{element.title}</Button>
))
})
}
</div>
)
}
export default ImportantTopics;
There are two things to note here:
{}
is used, you should use return
as stated in the other answers.key
is required. I've given index as key in the example. If any unique identifier is available in your case, I'd recommend using that.Upvotes: 0
Reputation: 1862
You need to return an Element or an array of Element. You a re not returning anything here
Upvotes: 0