3

I have data of nested objects in which I am getting data of my requirement, Now I want to loop through that object and render on UI, But I am not getting Idea how to do that as the UI is fully Dynamically dependent on data.

My data

const countData = {
  "current_month": {
    "total_employes": 6,
    "ariving": "+3",
    "exiting": "-1",
    "current_month": "April    2020",
    "__typename": "CurrentMonthTotalEmp"
  },
  "previous_month": {
    "total_employes": "3",
    "arrived": "+2",
    "exited": "-2",
    "previous_month": "March 2020",
    "__typename": "PrevMonthTotalEmp"
  },
  "__typename": "CurPrevMonthEmps"
}

to make it as array I doing this

const finalData =Object.entries(countData);

Now I want to loop this

please check my code-sandbox for full code

here in my code-sandbox I am rendering statically with HTML

4
  • How is the UI/data dynamic? Where are you trying to render this finalData? What is your expected result? Commented Apr 7, 2020 at 7:26
  • @DrewReese please check the link of code sandbox I have provided codesandbox.io/s/ecstatic-antonelli-z2c59 this, I am making my Ui using static HTML only, that I want to do dynamic with looping Commented Apr 7, 2020 at 7:30
  • Yes, my questions stemmed from your sandbox since I saw no attempts at mapping anything and it isn't overtly clear what is dynamic. Do you only ever display two months data? Or are there going to be more? Do you want to map that "weird" __typename property as well? Commented Apr 7, 2020 at 7:34
  • @DrewReese no __typename is not going to be mapped it is coming because I am using react-apollo-client, dynamic is the whole UI as you can see currently I am puting year arrived everything statically, I want to put them from JSON data now and it is always going to be two month data only only counts and month year will vary. Commented Apr 7, 2020 at 7:39

5 Answers 5

3

Most of your React applications will use data to render a UI. That's what React excels in.

Step 1: Create a reusable component

You'll have to create a React component which receives the props for each month. (total_employees, ariving, exiting and current_month) and renders them correctly.

for example:

const MonthComponent = ({ total_employees, ariving, exiting, current_month }) => {

  //above return you can alter your data however you want using normal javascript

  return (
    //in 'return' you can return HTML or JSX to render your component.
    <div>
      <p>{total_employees}</p>
      <p>{ariving}</p>
      <p>{exiting}</p>
      <p>{current_month}</p>
    </div>
  );
};

Step 2: Loop over your data and render your reusable component

Now in your parent component you can loop over your array of data.

const ParentComponent = () => {

  const countData = {
    "current_month": {
      "total_employes": 6,
      "ariving": "+3",
      "exiting": "-1",
      "current_month": "April    2020",
      "__typename": "CurrentMonthTotalEmp"
    },
    "previous_month": {
      "total_employes": "3",
      "arrived": "+2",
      "exited": "-2",
      "previous_month": "March 2020",
      "__typename": "PrevMonthTotalEmp"
    },
    "__typename": "CurPrevMonthEmps"
  }

  const months = Object.keys(countData); // ["current_month", "previous_month"]

  return (
    months.map(month => (
      // map over months and render your reusable component for each month
      <MonthComponent {...countData[month]} />
    ))
  );
};

Note: Spreading over ...countData[month] is a shorthand property to pass every key-value pair of countData[month] as a prop. I could also have written:

<MonthComponent
  total_employees={countData[month].total_employees}
  arrived={countData[month].arrived}
  exited={countData[month].exited}
  previous_month={countData[month].previous_month}
/>
Sign up to request clarification or add additional context in comments.

3 Comments

I don't thing creating two components are required here, I have tried looping through map but, had issue.
Your sandbox example showcased 2 very similar UI "blocks" It's advised to create a separate component for such blocks as to minimise having to write the same piece of code twice.
But besides that, if you wish to not use a second component, you could still map over Object.keys and render whatever you need dynamically within the map function.
1

There is a lot of code duplication, we want to reduce that (DRY Principle). First, find the common code that abstractly describes your UI, i.e. a component that has a month/year label, some arrive/exit fields & labels, and an employee count. Convert what you want displayed to a component that takes these "standardized" props.

const MonthData = ({
  arrive,
  arriveLabel,
  exit,
  exitLabel,
  totalEmployees,
  month,
}) => (
  <Fragment>
    <label className="monthYr" align="left">
      {month}
    </label>
    <div className="row countDiv">
      <div className="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6 total">
        <label className="totalHeading">Total employees</label>
        <div className="totalCount">{totalEmployees}</div>
      </div>

      <div className="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
        <button className="btn btn-outline-secondary button_Count form-control">
          {arriveLabel}
          <span className="badge badge-pill badge-primary ml-2">
            {arrive}
          </span>
        </button>
        <button className="btn btn-outline-secondary form-control">
          {exitLabel}
          <span className="badge badge-pill badge-primary ml-2">
            {exit}
          </span>
        </button>
      </div>
    </div>
  </Fragment>
);

I don't think I'd map these as you have different labeling for previous vs. current months, and you only ever display 2 months at a time. Just destructure from the countData the two months' data.

const { current_month, previous_month } = countData;

return (
  <div className="row container-fluid">
    <div className="form-control graphHeading"> Manpower Graph</div>
    <div className="col-12 col-sm-12 col-md-12 col-lg-12 col-xl-12">
      <div className="row widthContainer">
        <div className="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
          <MonthData
            arrive={previous_month.arrived}
            arriveLabel="arrived"
            exit={previous_month.exited}
            exitLabel="exited"
            month={previous_month.previous_month}
            totalEmployees={previous_month.total_employees}
          />
        </div>
        <div className="col-12 col-sm-12 col-md-6 col-lg-6 col-xl-6">
          <MonthData
            arrive={current_month.arriving}
            arriveLabel="arriving"
            exit={current_month.exiting}
            exitLabel="exiting"
            month={current_month.current_month}
            totalEmployees={current_month.total_employees}
          />
        </div>
      </div>
    </div>
  </div>
);

7 Comments

hey can you help me with codesandbox example so I can check live example
@manishthakur You mean copy/paste my code into your sandbox? Sure.
Can't I do this in single component as I have lot of other things related to this
@manishthakur codesandbox.io/s/…
Nothing, but please look as it is not showing up total no of employes
|
1

You can do something like this in your JSX code:

{finalData.map(value => (
  <div>{value.something}</div>
))}

Comments

1

you can use :

{
    Object.keys(countData).map(key=>{
        const month = countData[key]
        return(
            //you have access to month
            <div>{month.total_employes}</div>
        );
    })
}

Comments

1

First, you need to convert the countData into a proper structure over which we can run our loop. to do that you need to change how you convert it to array to the following

const finalData = Object.values(countData)

After doing so we can now loop over the finalData variable using a map function like this.

{finalData.map(data => (
  <div>{data.total_employes}</div>
  <div>{data.ariving}</div>
))}

Moreover to handle missing key/values in the object you can do the following

{finalData.map(data => (
  <div>{data.total_employes ? data.total_employes : 'NA'}</div>
  <div>{data.ariving ?  data.ariving : 'NA'}</div>
))}

Hope this helps

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.