Home > Enterprise >  how to map objects in javascript/ reactjs and use its key and values sepreately
how to map objects in javascript/ reactjs and use its key and values sepreately

Time:05-20

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>

enter image description here

{ '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's keys. This way you can do Object.keys(obj).map(key => { ... }), you already have the key, and to get the value of it, you can simply do obj[key].

  • Object.entries(obj) is very similar to Object.keys, but returns an array of arrays, each of these arrays is composed of the key and its value ([key, value]). So you can do Object.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;

  • Related