Mapping an array with API data Array in an Array

Hi folks,

I am trying to map over data from this API

So the json is like this:

{
  "disruptionTimeWindow": {
    "start": "-271771-04-29T08:07:01.000",
    "end": "275760-01-09T19:40:21.000"
  },
  "disruptions": [
    {
      "id": "6684_TfWM",
      "mode": "BUS",
      "disruptionTimeWindow": {
        "start": "1567382400000",
        "end": "1585699140000"
      },
      "publicationTimeWindow": {
        "start": "1567382400000",
        "end": "1585699140000"
      },
      "disruptionSeverity": "normal",
      "title": "Construction for West Midlands Metro extension",
      "description": "From<strong> Monday 2nd</strong> <strong>September</strong><br /><br />Due to works on the Five Ways extension of the West Midlands Metro, stops BR5 and BR6, the outbound stop nearest the Five Ways roundabout and the two stops outside the Hilton Garden Inn on Sheepcote Street are now closed, and services using them are diverted.<br /><br /><strong>NXWM 9, 10, 10H, 12, 12A, 13, 13A, 23, 24, 126, X8 and X10</strong> are affected.<br /><br /><strong>From City</strong> all routes <strong>except 10H</strong> towards Harborne or Bearwood, the diversion route will be Sheepcote Street, Grosvenor Street West, Friston Avenue, Ladywood Middleway, Five Ways Island then normal lines of route.<br /><br /><strong>10H</strong> will be diverted from City via Great Charles Street, Parade, Sandpits, Summerhill Road, Ladywood Middleway, Aleston Street then normal line of route.<br /><br /><strong>Towards City</strong> for routes <strong>9, 10, 12, 12A, 13, 13A, 126, X8 and X10</strong> the diversion route will be from Five Ways Island, Broad Street, Ryland Street, Grosvenor Street West, Sheepcote Street then normal line of route.<br /><br /><strong>Towards City</strong> for route <strong>10H 23 & 24</strong> will use normal line of route into the City Centre. <br /><br />Temporary stops out of City will be in place at Sheepcote Street outside The Crescent Theater, Grosvenor Street West and Ladywood Middleway at Five Ways.<br />Temporary stops into City will be in place at Ryland Street/Grosvenor Street West, Greosvenor Street West/Sheepcote Street.",
      "lat": 111,
      "lon": 222,
      "route": null,
      "serviceAffected": [
        {
          "id": "82154",
          "operatorCode": "NXB",
          "routeDesc": "Queen Elizabeth Hospital to Birmingham",
          "serviceNumber": "10h",
          "direction": "inbound"
        },
],
}

So on and so forth. I have a map function:

 {disruptions.length > 0 ? (
          disruptions.map(post => {
            return (
              <div key={post.id}>
                <br />
                {post.title}
                <br />
                {post.description}
                <br />
                {post.disruptionSeverity}
                <br />
                {post.id}
                <br />
                {post.title}
                <br />
                {post.mode}
              </div>
            );
          })
        ) : (
          <div>
            <div className="wmnds-loader" />
          </div>
        )}

Which does output the data:

But I want to try and get the data out of:

   "serviceAffected": [
        {
          "id": "82154",
          "operatorCode": "NXB",
          "routeDesc": "Queen Elizabeth Hospital to Birmingham",
          "serviceNumber": "10h",
          "direction": "inbound"
        },
],

I’ve seen that someone else in the forum wanted to do the same here and that @camperextraordinaire managed to help them with the solution here:

The question being, how do I map over a map or get the data out of serviceAffected array?!

Thank you,

John.

P.S - I created a sandbox here:

But for some reason the data doesn’t load but I did add Axios as a package!

Anything you write inside curly braces { } is valid JavaScript, meaning {post.disruptionSeverity} is javascript command that selects nested array. Looking at your line 2, it seems like you know what to do next - repeat process for this array :slight_smile:

1 Like

It’s also useful to isolate things and write them declaratively as components. So eg

....
<div key={post.id}>
  <br />
  {post.title}
  <br />
  {post.description}
  <br />
  {post.disruptionSeverity}
  <br />
  {post.id}
  <br />
 {post.title}
  <br />
 {post.mode}
 <AffectedServices services={post.servicesAffected} />
</div>
......

So you would now have to write a component called AffectedServices which takes that servicesAffected array as a prop and renders your HTML based on it.

2 Likes

Ah got you! So in that case I would create a new component and the call it in like:

<AffectedServices services={post.servicesAffected} />

But my question still remains how would one get that data out the map as you couldn’t do this right:

post.serviceAffected.operatorCode

I’m #lost!

Thank you :slight_smile:

What is it that you want the output to be? Cos with that array, there could be multiple affected services, so you wouldn’t just want a single value. You would do exactly the same as you did for the main component though, you just treat it as it’s own little thing, for example:

const AffectedServices = ({ servicesAffected }) => (
  <>
    { servicesAffected.map((service) => <p key={service.id}>{service.operatorCode}</p>) }
  </>
);
1 Like

Right ok, I get you! I am going to get it into its own component, call its own map and then call then into the parent component, here goes. Thanks Dan :slight_smile:

1 Like

Hey so I created its own component but I am doing another componentDidMount call and api call and this seems a bit too much when I have already done componentDidMount & api call.

Can I not just use the api call already, also do I use another .map for the AffectedServices

Cheers :slight_smile:

Nonono, you already have that data. The component depends on what you give it in the props, it doesn’t need any lifecycle methods. Array of services in as props -> JSX result comes out.

1 Like

ok I need to go over this in the curriculum and see if I can figure it out! Thanks for the help this far :wink:

Finally:

   return (
      <div>
        {disruptions.length > 0 ? (
          disruptions.map(post => {
            return (
              <div key={post.id}>
                <h2>Disruptions:</h2>
                <em>operatorCode below</em>
                <br />
                {post.title}
                <br />
                {post.description}
                <br />
                {post.disruptionSeverity}
                <br />
                {post.id}
                <br />
                {post.title}
                <br />
                {post.mode}

                <h2>This is what I needed - A .map in a .map!!!</h2>
                {post.serviceAffected.map(affected => (
                  <div key={affected.id}>
                    <h5>Operator code:</h5>
                    {affected.operatorCode}
                    <h5>routeDesc:</h5>
                    {affected.routeDesc}
                    <h5>serviceNumber:</h5>
                    {affected.serviceNumber}
                    <h5>direction</h5>
                    {affected.direction}
                  </div>
                ))}
              </div>
            );
          })
        ) : (
          <div>
            <div className="wmnds-loader" />
          </div>
        )}
      </div>
    );

@DanCouper would be proud!! Thanks for the help all :slight_smile: I’ll be back with more questions again soon :wink:

1 Like