i am trying to use data from an object that made by merging two arrays after making an object i am stuck at the part of how to map that object?
this is the javascript:-
class CampaignIndex extends Component {
static async getInitialProps() {
const campaigns = await factory.methods.getDeployedCampaigns().call(); //first array of dataset
const data = await factory.methods.getDeployeddata().call(); //2nd array of dataset
const sum = [
{
description: data,
location: campaigns,
},
];
var result = Object.assign.apply(
{},
campaigns.map((v, i) => ({ [v]: data[i] }))
);// merged them into one object
console.log(result);
// {
// '0x0B1B7F35442bC8b122B612872e63860246Ae070F': 'this is a test',
// '0xB8364AE9ce43D1136CbB74321302B3738b64452D': 'hope this works',
// '0xD3E37a011d4c00109341D1de06659214e77c3695': 'hi'
// }
//console.log(data);
//console.log(campaigns);
return {
campaigns,
data,
result,
};
}
renderCampaigns() {
const { data, beta } = this.props;
const items = result.map((term) => {
return {
header: term.key(),
meta: term.values(),
description: (
<Link
as={`/campaigns/${term.values()}`}
// href={{
// pathname: `/campaigns/show/`,
// query: { address },
// }}
>
<a>view campaign</a>
</Link>
),
fluid: true,
};
});
return <Card.Group items={items} />;
}
the only way it kinda worked but not correctly the only way i know was by using two arrays but it showed all of the description in one single line cause i was only able to map the address
class CampaignIndex extends Component {
static async getInitialProps() {
const campaigns = await factory.methods.getDeployedCampaigns().call();
const data = await factory.methods.getDeployeddata().call();
const beta = data.map((description) => <h3>{description}</h3>);
const sum = [
{
description: data,
location: campaigns,
},
];
console.log(data);
console.log(campaigns);
return {
campaigns,
data,
beta,
};
}
renderCampaigns() {
const { data, beta } = this.props;
//const betas = data.map(description);
const items = this.props.campaigns.map((address) => {
return {
header: data,
meta: address,
description: (
<Link
as={`/campaigns/${address}`}
href={{
pathname: `/campaigns/show/`,
query: { address },
}}
>
<a>view campaign</a>
</Link>
),
fluid: true,
};
});
return <Card.Group items={items} />;
<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>
{ '0x0B1B7F35442bC8b122B612872e63860246Ae070F': 'this is a test', //the key is the address '0xB8364AE9ce43D1136CbB74321302B3738b64452D': 'hope this works', //the value is the description '0xD3E37a011d4c00109341D1de06659214e77c3695': 'hi' }
i want to render it in such a way that for every address it should create a new card group which i did from the code above but i could not insert the description in the same way cause if i map it out side the render it showed all the description in the same card unlike the addresses. pls help!!
CodePudding user response:
There are a couple of ways to loop through an object's properties. You can use a couple of methods: Object.keys()
and Object.entries()
are the most appropriate for your case.
Object.keys(obj)
receives an object (obj
) and returns an array of the object'skeys
. This way you can doObject.keys(obj).map(key => { ... })
, you already have thekey
, and to get the value of it, you can simply doobj[key]
.Object.entries(obj)
is very similar toObject.keys
, but returns an array of arrays, each of these arrays is composed of the key and its value ([key, value]
). So you can doObject.entries(entry => { ... })
, and to access the entry's key:entry[0]
. Same thing for the entry's value:entry[1]
.
Personally, I prefer to use Object.keys
because it doesn't use the indexes to access the keys and values, but both should work.
I believe your code would look like this:
renderCampaigns() {
const { data, beta } = this.props;
const items = Object.keys(result).map((key) => {
return {
header: key,
meta: result[key],
description: (
<Link
as={`/campaigns/${result[key]}`}
// href={{
// pathname: `/campaigns/show/`,
// query: { address },
// }}
>
<a>view campaign</a>
</Link>
),
fluid: true,
};
});
return <Card.Group items={items} />;
}
CodePudding user response:
First of all, provide you a quick answer but it's not a good one:
const items = this.props.campaigns.map((address, index) => {
return {
header: data?.[index],
meta: address,
description: (
<Link
as={`/campaigns/${address}`}
href={{
pathname: `/campaigns/show/`,
query: { address },
}}
>
<a>view campaign</a>
</Link>
),
fluid: true,
};
});
return <Card.Group items={items} />;
Bellow provides you with another refactor version for your reference.
It's always better to handle data first for better-maintaining purposes.
So if the order and indexing of 2 arrays are equal, you should ask API developers to combine data together in one single API.
If they're not able to do that, then we could use promise all to combine data together at the beginning.
Let me use React hook to represent it since it's convenient to write and the performance is better.
import React, { useEffect, useState } from 'react';
import Card from 'ooo'
function getCampaigns() {
const getDeployedCampaignApiUrl = 'https://jsonplaceholder.typicode.com/todos/2'
const getDeployedDataApiUrl = 'https://jsonplaceholder.typicode.com/todos/3'
const urls = [getDeployedCampaignApiUrl,
getDeployedDataApiUrl]
return Promise.all(urls.map(url => fetch(url)
.then(response => response.json())
.then(responseBody => responseBody.list)))
.then(lists => {
const result =
lists[0].map((item, i) => Object.assign({}, item, lists[1][i]));
})
.catch(err => {
console.error('Failed to fetch one or more of these URLs:');
console.error(err);
});
}
function Campaign() {
const [list, setList] = useState([]);
useEffect(() => {
let mounted = true;
getCampaigns()
.then(items => {
if(mounted) {
setList(items)
}
})
return () => mounted = false;
}, [])
return (
<>
{list.map(item => <Card.Group key={item.id} item={Object.assign({}, item, {
description: (
<Link
as={`/campaigns/${item.id}`}
// href={{
// pathname: `/campaigns/show/`,
// query: { item.address },
// }}
>
<a>{item.header}</a>
</Link>
)
})} />)}
</> )
}
export default Compaign;