Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping through a Map in React

I have a Map object:

let dateJobMap = new Map();

for (let jobInArray of this.state.jobs) {
  let deliveryDate: Date = new Date(jobInArray.DeliveryDate);
  let deliveryDateString: string = deliveryDate.toLocaleDateString("en-US");

  if (dateJobMap.has(deliveryDateString)) {
    let jobsForDate: IDeliveryJob[] = dateJobMap.get(deliveryDateString);
    jobsForDate.push(jobInArray);
  }
  else {
    let jobsForDate: IDeliveryJob[] = [jobInArray];
    dateJobMap.set(deliveryDateString, jobsForDate);
  }
}

In my render method, I want to call a TruckJobComp object for each delivery job in the value's array to display it:

        <div className={ styles.column }>
          <p className={ styles.description }>{escape(this.props.description)}</p>

          {
            dateJobMap.forEach(function(jobsForDate, dateString) {
              jobsForDate.map(job => (
                <TruckJobComp job = { job } />
              ))
            })
          }
        </div>

This seems like it should work but doesn't. It never creates a TruckJobComp. I do a .forEach iteration on my Map, and for each value's array, I use .map to get the individual job object to send to TruckJobComp object.

When I create a temp array to grab the jobs from the last loop:

let tempJobs: IDeliveryJob[];

and in the loop add in:

  if (dateJobMap.has(deliveryDateString)) {
    let jobsForDate: IDeliveryJob[] = dateJobMap.get(deliveryDateString);
    jobsForDate.push(jobInArray);

    tempJobs = jobsForDate;
  }

and then use that array in the render:

          <div className={ styles.column }>
            <p className={ styles.description }>{escape(this.props.description)}</p>
            {
              tempJobs.map(job => (
                <TruckJobComp job = { job }/>
              ))
            }
          </div>

It displays as expected.

I do have a warnings in Visual Studio Code:

Warning - tslint - ...\TruckDeliverySchedule.tsx(104,38): error no-function-expression: Use arrow function instead of function expression

I don't know enough to understand. Line 104 corresponds with:

dateJobMap.forEach(function(jobsForDate, dateString) {

I am very new to this so I'm not 100% sure how most of this works. Just trying to put pieces I've learned together to get things to work.

Second Edit:

{escape(this.props.description)}

{
  [...dateJobMap.keys()].map(jobsForDate => // line 154
    jobsForDate.map(job => (
      <TruckJobComp job = { job } />
    ))
  )
}

Produces error:

[09:06:56] Error - typescript - src\...\TruckDeliverySchedule.tsx(154,27): error TS2461: Type 'IterableIterator<any>' is not an array type.
like image 785
Holden1515 Avatar asked Aug 01 '18 16:08

Holden1515


People also ask

How do you loop through a map in React?

Use the Object. keys() method to get an array of the object's keys. Use the map() method to iterate over the array of keys.

How do you loop through a list in React?

To loop through an array of objects in React:Use the map() method to iterate over the array. The function you pass to map() gets called for each element in the array. The method returns a new array with the results of the passed in function.

Why We Use map instead of for loop in React?

map generates a map object, for loop does not return anything. syntax of map and for loop are completely different. for loop is for executing the same block of code for a fixed number of times, the map also does that but in a single line of code.

Can we use forEach instead of map in React?

You are correct, forEach doesn't return anything, use map instead, it will return an array of JSX components.


Video Answer


2 Answers

dateJobMap.forEach(...) returns undefined, so it cannot be mapped to a collection of elements.

ES6 maps have forEach method for compatibility purposes (generally for..of is preferred to iterate over iterables) and don't have map method. A map should be converted to array first, then it could be mapped to an element. Since values aren't used, only keys need to be retrieved:

  {
    [...dateJobMap.keys()].map(jobsForDate =>
      jobsForDate.map(job => (
        <TruckJobComp job = { job } />
      ))
    )
  }
like image 163
Estus Flask Avatar answered Oct 16 '22 12:10

Estus Flask


All this warning is saying is that instead of using the syntax function(jobsForDate, dateString) {} you should use the syntax (jobsForDate, dateString) => {}.

The reason could be the way this is scoped in arrow functions versus function expressions. See this post.

My guess as to the reason your first approach didn't work but your second one did is that forEach doesn't actually return an array, and if it did, calling map within forEach would return an array of arrays (but, again, it doesn't). Not sure how React would handle that, but React does know how to handle a single array, which is what your last approach returns.

like image 2
jaredkwright Avatar answered Oct 16 '22 13:10

jaredkwright