Can we have dynamic headers in spreadjs? - javascript

I have integrated spreadJS with react framework. In spreadjs they only use the header name specified in JSON and accordingly the data get displayed in the spreadsheet.
Can we have dynamic headers and their respective value using JSON?
import { SpreadSheets, Worksheet, Column } from '#grapecity/spread-sheets-react';
this.data = [
{
"id": 1934,
"date": "2018-11-01",
"value": 10.0
},
{
"id": 1935,
"date": "2018-12-01",
"value": 10.0
},
{
"id": 1935,
"date": "2018-12-01",
"value": 10.0
}
]
class SpreadJsSample extends React.Component {
render() {
return (
<div>
<SpreadSheets>
<Worksheet data={this.data}>
{this.data.map(index => {
<Column width={150} data={index.date} />;
})}
</Worksheet>
</SpreadSheets>
</div>
);
}
}
I am getting following errors
The above error occurred in the Worksheet component:
Uncaught Cannot read property 'type' of null
Any help will be appreciated. Thanks!

The function you're passing to .map() isn't returning anything, so your array of columns is currently [undefined, undefined, undefined].
You just need to return the <Column>:
{this.data.map(index => {
return <Column width={150} data={index.date} />;
})}
or
{this.data.map(index => <Column width={150} data={index.date} /> )}

Related

How to fetch and render object of objects in next js?

I have following code and I am trying to display the data from the object of objects. The error that I receive is TypeError: Cannot read properties of undefined. I understand that the data isn't in the format of 'array of objects', however I still don't know how to properly map it. I would appreciate some help here...
import Layout, { siteTitle } from '../components/layout';
import { useState, useEffect } from 'react'
export default function Home({ allPosts }) {
return (
<Layout home>
<Head>
<title>{siteTitle}</title>
</Head>
<section>
{Object.values(allPosts.bpi).map(({ section, idx }) => (
<li className={utilStyles.listItem} key={idx}>
{section.description}
<br />
{section.code}
<br />
</li>
))}
</section>
</Layout>
);
}
export async function getStaticProps() {
let data = [];
let error = "";
try {
const res = await fetch(
"https://api.coindesk.com/v1/bpi/currentprice.json",
);
data = await res.json();
} catch (e) {
error = e.toString();
}
return {
props: {
allPosts: data,
error,
},
};
}
Logged data: enter image description here
Object looks like this
{
"chartName": "Bitcoin",
"bpi": {
"USD": {
"code": "USD",
"symbol": "$",
"rate": "20,220.5728",
"description": "United States Dollar",
"rate_float": 20220.5728
},
"GBP": {
"code": "GBP",
"symbol": "£",
"rate": "16,896.1488",
"description": "British Pound Sterling",
"rate_float": 16896.1488
},
}
}
You don't access the USD and GBP objects. You are just getting their names. But you can access them by name like this:
<section>
{Object.values(allPosts.bpi).map((section, idx) => (
<li className={utilStyles.listItem} key={idx}>
{allPosts.bpi[section].description}
<br />
{allPosts.bpi[section].code}
<br />
</li>
))}
</section>
EDIT
It should be section.description instead of allPosts.bpi[section].description. Same for the object code.
<section>
{Object.values(allPosts.bpi).map((section, idx) => (
<li className={utilStyles.listItem} key={idx}>
{section.description}
<br />
{section.code}
<br />
</li>
))}
</section>
You are using the map method wrong.
Try this.
Object.values(allPosts.bpi).map((section, idx) => ....

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

How to send array of objects in props to a custom component in React Native?

I have an array when I fetch from the API by using axios get request as follows:
useEffect(async () => {
console.log("here");
let accessToken = await AsyncStorage.getItem("accessToken");
const response = await axios
.get(API_URL + "/feed", {
headers: {
Authorization: "Bearer " + accessToken,
},
})
.then((response) => {
setFeedItems([]);
setFeedItems((feedItems) => [...feedItems, ...response.data]);
setIsLoading(false);
});
}, []);
I have a custom component which is Report.js and I want to send some information from this screen to that component by using the following code:
{isLoading == false && (
<FlatList
style={{ marginLeft: 10, marginRight: 10 }}
data={feedItems}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<Report
name="mustafa"
username="mustafa123"
responsibleInstitution="responsible"
userId={item.userId}
category={item.category}
location={item.location}
institutionId={item.institutionId}
description={item.description}
upvotes={item.upvotes}
comments={item.comments}
/>
)}
></FlatList>
The shape of the data that is coming from the API is as follows:
[
{
"id": "6228a72cfc2ce87bb0b5f908",
"userId": "61cab704ee5f9a5cc3bd844c",
"institutionId": "61cabb2da10a9147a53e6480",
"solutionId": null,
"description": "Kayıp ilanı..",
"category": "Missing",
"comments": [
{
"id": "6228c0933ab2f166af0a9d23",
"userId": "61cab704ee5f9a5cc3bd844c",
"text": "Tamam kardeş anladık",
"date": "2022-03-09T14:58:27.091+00:00"
},
{
"id": "6228c98534572422056eb565",
"userId": "61cab704ee5f9a5cc3bd844c",
"text": "Tamam kardeş anladık 3",
"date": "2022-03-09T15:36:37.256+00:00"
}
],
"upvotes": [
"61cab704ee5f9a5cc3bd844c"
],
"location": null,
"report_image_link": null,
"file": null,
"date": "2022-03-09T13:10:04.273+00:00"
},
As you can see from the data, the 'comments' field has an array of objects with id, userId, text, and date fields. Whenever I run the code, I get the following error which is caused by the comments={item.comments} line.
The error: Objects are not valid as a React child (found: object with keys {id, userId, text, date}). If you meant to render a collection of children, use an array instead.
What I want to do is that, whenever user click a button in the Report.js component, I want to open up a modal and present the comments to the user on that component. Do you think I should change my way? How can I send the comments information to the Report component? If my approach is incorrect, what should I do?
Since comments is an array of objects, you cannot pass it as a child to a Text component. Now, it depends on how you want to visualize your data. Here is a possible solution using FlatList. You could replace the rendered component with whatever suits you the best.
const dummyData = [
{
"id": "6228c0933ab2f166af0a9d23",
"userId": "61cab704ee5f9a5cc3bd844c",
"text": "Tamam kardeş anladık",
"date": "2022-03-09T14:58:27.091+00:00"
},
{
"id": "6228c98534572422056eb565",
"userId": "61cab704ee5f9a5cc3bd844c",
"text": "Tamam kardeş anladık 3",
"date": "2022-03-09T15:36:37.256+00:00"
}
]
const App = () => {
const [data, setData] = useState(dummyData);
return (
<SafeAreaView style={{ flex: 1 }}>
<View>
<FlatList
data={data}
renderItem={({item}) => {
return <Text style={{margin: 20}}>`ID: ${item.id} userId: ${item.userId} text: ${item.text} date: ${item.date}`</Text>
}}
keyExtractor={(item, index) => index.toString()}
/>
</View>
</SafeAreaView>
);
};

How to fetch inner API data in ReactJS?

What I am trying to do is fetch the inner data of blog_set. But in my case, I'm getting a null value (usually nothing is output).
Is this the correct way to get the value: {bloglist.blog_set.title} ?
api-data:
[
{
"url": "http://localhost:8000/api/category/brown",
"id": 1,
"title": "brown",
"slug": "brown",
"image": "http://localhost:8000/media/category/bg_1.jpg",
"description": "",
"created_on": "2020-05-08T15:21:02Z",
"status": true,
"blog_set": [
{
"id": 6,
"url": "http://localhost:8000/api/blog_detail/test3",
"title": "test3",
"slug": "test3",
"image": "http://localhost:8000/media/blog/author.jpg",
"description": "test3",
"created_on": "2020-05-13T13:36:45Z",
"status": true,
"category": [
1
]
}
]
}
]
./src/Category.js
export default class App extends Component{
state = {
bloglist: [],
};
componentDidMount() {
this.fetchData();
}
fetchData = async () => {
try {
const response = await fetch("http://localhost:8000/api/category");
const jsonResponse = await response.json();
this.setState({ bloglist: jsonResponse });
} catch (error) {
console.log(error);
}
};
render(){
{
const { bloglist } = this.state;
return(
<div>
{bloglist.map((bloglist) => (
<div>
<h3 class="mb-2">{bloglist.blog_set.title}</h3>
</div>
))}
</div>
);
}
}
}
blog_set is an array so it does not have an attribute/memeber/item called title. You should define at what index you want the data.
bloglist.blog_set[0].title
Or iterate over blog_set too
As bloglist is also an array you need to use one more .map() or as bloglist[0].blog_set[0].title
Example:
{bloglist.map((bloglist) => (
<div>
<h3 class="mb-2">{bloglist.blog_set.map(i=> i.title)}
</h3>
</div>
))}
blogList.map() will iterate the parent Array of objects to get blog_set and blog_set.map() will now iterate the blog_set to get list title
{bloglist.map((bloglist) =>(
<div>
<h3 class="mb-2">{bloglist.blog_set.map((list)=>( list.title)}</h3>
</div>)}
blog_set is an array. In order to iterate it, use map and {title}. In each iteration of your blog_set object, there is a key named title (destructured object).
<div>
{bloglist.map((bloglist) => (
<div>
<h3 class="mb-2">{blog_set.map(({title})=>title))}</h3>
</div>
))}
</div>

Props data are not rendering

I have a problem rendering my props data
Here I'm trying to pass props to a component with mapped data from a sample data set
const weatherComponents = weatherData.items.map(weather => {
return(
<div key={weather.forecasts.area}>
<WeatherForecast
name={weather.forecasts.area}
condition={weather.forecasts.forecast}>
</WeatherForecast>
</div>
)})
return(
{weatherComponents} )
This is the component
function WeatherForecast(props) {
return(
<div>
<p>Name: {props.name}</p>
<p>Condition: {props.condition}</p>
</div>
)}
This is the sample data set
{
"area_metadata": [
{
"name": "Yishun",
"label_location": {
"latitude": 1.418,
"longitude": 103.839
}
}
],"items": [
{
"forecasts": [
{
"area": "Yishun"
"forecast" : "cloudy"
}
]}
]}
In my browser, it shows Warning: Each child in a list should have a unique "key" prop. and the data are not rendering, it only appears "Name: " without the area name from the data set. Am I mapping the data in the wrong way? Help TT
You have 2 options ... well, 3.
You need an array in "area_metadata" and "items":
1.1. The fast solution:
const weatherComponents = weatherData.items.map(weather => {
return(
<div key={weather.forecasts[0].area}>
<WeatherForecast
name={weather.forecasts[0].area}
condition={weather.forecasts[0].forecast}>
</WeatherForecast>
</div>
)
})
return({weatherComponents})
1.2 The right solution:
const weatherComponents = weatherData.items.map(weather => {
return weather.forecasts.map( casts => (
<div key={casts.area}>
<WeatherForecast
name={casts.area}
condition={casts.forecast}>
</WeatherForecast>
</div>
))
})
return({weatherComponents})
2. You do not need an array:
{
"area_metadata": [
{
"name": "Yishun",
"label_location": {
"latitude": 1.418,
"longitude": 103.839
}
}
],
"items": [
{
"forecasts": {
"area": "Yishun"
"forecast" : "cloudy"
}
}
]
}
Just replace
const weatherComponents = weatherData.items.map(weather => {
return(
<div key={weather.forecasts.area}>
<WeatherForecast
name={weather.forecasts.area}
condition={weather.forecasts.forecast}>
</WeatherForecast>
</div>
)})
return(
{weatherComponents} )
with
const weatherComponents = weatherData.items.map(weather => {
const {area, forecast} = weather.forecasts[0];
return(
<div key={area}>
<WeatherForecast
name={area}
condition={forecast}>
</WeatherForecast>
</div>
)})
return(
{weatherComponents} )

Categories