how to map through data grouped with lodash

I’ve got an array of 35+ store locations that I’m returning from my database. The raw data looks like this:

[
  {
    id: 12,
    dealer_code: "TOR",
    name: "Grinyer Doors & Closets",
    company_picture: "company_blank.png",
    URL: "http://toronto.onedaydoorsandclosets.com",
    address: "2225 Dundas Street East",
    city: "Mississauga",
    state: "ON",
    zip: "L4X 1M3",
    phone: "6473601783",
    hrs_mf: "T/W 10:00 am - 6:00 pm, Th 11:00",
    hrs_sat: "F/Sat 10:00 am to 4:00 pm",
    hrs_sun: "Sun/Mon By Appointment",
    owner: "Andy J. Grinyer and Ashley Grinyer",
    sales_email: "[email protected]",
    dealer_emails: "[email protected]",
    google_email: "[email protected]",
    google_cal_embed:
      '<iframe src="https://calendar.google.com/calendar/embed?mode=WEEK&height=600&wkst=2&bgcolor=%23FFFFFF&src=inquiry%40onedaytoronto.com&color=%230F4B38&src=onedaytoronto.com_27u9oep2iovpdkmpp5r1giojjo%40group.calendar.google.com&color=%23182C57&src=onedaytoronto.com_7no5uhj4j229c4jn3gd18dhj94%40group.calendar.google.com&color=%2342104A&src=onedaytoronto.com_p940ipdjjoftvavvh13gfot9tk%40group.calendar.google.com&color=%23853104&src=onedaytoronto.com_61h07lvglj5g7bmqj8aqt2r12k%40group.calendar.google.com&color=%232952A3&src=onedaytoronto.com_bno1ftb9nd9dskrfb6jnoft6d8%40group.calendar.google.com&color=%235F6B02&src=onedaytoronto.com_qjp37fdvq5v1n537qa283knsh0%40group.calendar.google.com&color=%23875509&ctz=America%2FNew_York" style="border-width:0" width="800" height="600" frameborder="0" scrolling="no"></iframe>',
    angies_list: "",
    facebook: "",
    google_plus: "",
    houzz: "",
    yelp: "",
    callrail_id: "-1",
    callrail_company_id: "-1",
    contractor_num: "",
    subdomain: "toronto",
    geo_area: "Toronto Ontario",
    page_title: "Grinyer Doors & Closets",
    meta_description:
      "Grinyer Doors & Closets in Mississauga, Toronto Ontairo offers beautiful Interior Doors, Closet Doors and Closet Organizers, installed in your home with no mess, in just One Day",
    meta_keywords:
      "Grinyer Doors & Closets, Toronto ON area, Beautiful Interior Doors, Closet Doors, Closet Organizers, installed in one day",
    meta_geo_position: "43.62728980000001; -79.5649536",
    meta_geo_placename: "Toronto ON",
    meta_geo_region: "ON-CA",
    maps_embed:
      '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d92414.58558064821!2d-79.61798002218458!3d43.62827889693909!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x882b38034f543fcf%3A0x75bdba79ac2ed006!2s2225+Dundas+St+E%2C+Mississauga%2C+ON+L4X+1M3%2C+Canada!5e0!3m2!1sen!2sus!4v1510088324431" width="800" height="600" frameborder="0" style="border:0" allowfullscreen></iframe>',
    sm_maps_embed:
      '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d92414.58558064821!2d-79.61798002218458!3d43.62827889693909!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x882b38034f543fcf%3A0x75bdba79ac2ed006!2s2225+Dundas+St+E%2C+Mississauga%2C+ON+L4X+1M3%2C+Canada!5e0!3m2!1sen!2sus!4v1510088324431" width="280" height="200" frameborder="0" style="border:0" allowfullscreen></iframe>',
    corp_ga:
      "<!-- Global site tag (gtag.js) - Google Analytics -->rn<script async src="https://www.googletagmanager.com/gtag/js?id=UA-75410322-17"></script>rn<script>rn  window.dataLayer = window.dataLayer || [];rn  function gtag(){dataLayer.push(arguments);}rn  gtag('js', new Date());rnrn  gtag('config', 'UA-75410322-17');rn</script>",
    dealer_ga:
      "<!-- Global site tag (gtag.js) - Google Analytics -->rn<script async src="https://www.googletagmanager.com/gtag/js?id=UA-112934473-1"></script>rn<script>rn  window.dataLayer = window.dataLayer || [];rn  function gtag(){dataLayer.push(arguments);}rn  gtag('js', new Date());rnrn  gtag('config', 'UA-112934473-1');rn</script>",
    min_level_see_sales: 3,
    active: 1,
  },
  {
    id: 2,
    dealer_code: "MFR",
    name: "Modern Doors & Closets",
    company_picture: "company_blank.png",
    URL: "",
    address: "1904 UNITED WAY, SUITE 100rnMedford, OR 97504",
    city: "MEDFORD",
    state: "OR",
    zip: "97504",
    phone: "541-843-3007",
    hrs_mf: "",
    hrs_sat: "",
    hrs_sun: "",
    owner: "Ronnie Gobel",
    sales_email: "[email protected]",
    dealer_emails: "[email protected]",
    google_email: "",
    google_cal_embed: "",
    angies_list: "",
    facebook: "",
    google_plus: "",
    houzz: "",
    yelp: "",
    callrail_id: "-1",
    callrail_company_id: "-1",
    contractor_num: "225480",
    subdomain: "oregon",
    geo_area: "",
    page_title: "",
    meta_description: "",
    meta_keywords: "",
    meta_geo_position: "",
    meta_geo_placename: "",
    meta_geo_region: "",
    maps_embed: "",
    sm_maps_embed: "",
    corp_ga: "",
    dealer_ga: "",
    min_level_see_sales: 3,
    active: 1,
  },
  {
    id: 43,
    dealer_code: "PIT",
    name: "Pittsburgh Doors & Closets",
    company_picture: "company_blank.png",
    URL: "pittsburgh.onedaydoorsandclosets.com",
    address: "11269 Perry Highway",
    city: "Wexford",
    state: "PA",
    zip: "15090",
    phone: "724-200-7709",
    hrs_mf: "9:00-5:00 ",
    hrs_sat: "9:00-1:00 ",
    hrs_sun: "By appointment",
    owner: "Scott Satkoske",
    sales_email: "[email protected]",
    dealer_emails: "[email protected]",
    google_email: "[email protected]",
    google_cal_embed:
      '<iframe src="https://calendar.google.com/calendar/b/1/embed?height=600&amp;wkst=1&amp;bgcolor=%23FFFFFF&amp;src=sales%40pittdac.com&amp;color=%231B887A&amp;src=pittdac.com_ci0lflb7cmcsjt95k24n5e671o%40group.calendar.google.com&amp;color=%238C500B&amp;src=en.usa%23holiday%40group.v.calendar.google.com&amp;color=%23865A5A&amp;src=pittdac.com_bvdo8ueq7m77v5ppbmgk6frgc0%40group.calendar.google.com&amp;color=%235F6B02&amp;ctz=America%2FNew_York" style="border-width:0" width="800" height="600" frameborder="0" scrolling="no"></iframe>',
    angies_list: "",
    facebook:
      "https://business.facebook.com/pg/PittsburghDoorsAndClosets/reviews",
    google_plus: "https://business.google.com/site/l/05941407921024537876",
    houzz: "https://www.houzz.com/pro/pittsburgh-doors-and-closets",
    yelp:
      "https://www.yelp.com/biz/pittsburgh-doors-and-closets-wexford?osq=pittsburgh+doors+and+closets",
    callrail_id: "-1",
    callrail_company_id: "-1",
    contractor_num: "PA140165",
    subdomain: "pittsburgh",
    geo_area: "PITTSBURGH, PA",
    page_title: "Pittsburgh Doors & Closets",
    meta_description:
      "Pittsburgh Doors & Closets in Pittsburgh, offers beautiful Interior Doors, Closet Doors and Closet Organizers, installed in your home with no mess, in just One Day",
    meta_keywords:
      "Pittsburgh Doors & Closets, Pittsburgh, Pennsylvania area, Beautiful Interior Doors, Closet Doors, Closet Organizers, installed in one day",
    meta_geo_position: "40.6275; 80.0614",
    meta_geo_placename: "PITTSBURGH, PA",
    meta_geo_region: "PA-US",
    maps_embed:
      '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d8565.491436036575!2d-80.05813514061147!3d40.6219743315419!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8834899d3f9df1c1%3A0x53a2004389724ee7!2s11269+Perry+Hwy%2C+Wexford%2C+PA+15090!5e0!3m2!1sen!2sus!4v1527191360692" width="800" height="600" frameborder="0" style="border:0" allowfullscreen></iframe>',
    sm_maps_embed:
      '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d8565.491436036575!2d-80.05813514061147!3d40.6219743315419!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8834899d3f9df1c1%3A0x53a2004389724ee7!2s11269+Perry+Hwy%2C+Wexford%2C+PA+15090!5e0!3m2!1sen!2sus!4v1527191360692" width="280" height="200" frameborder="0" style="border:0" allowfullscreen></iframe>',
    corp_ga:
      "<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-75410322-1', 'auto'); ga('send', 'pageview');</script>",
    dealer_ga: "",
    min_level_see_sales: 3,
    active: 1,
  },
  {
    id: 56,
    dealer_code: "PHI",
    name: "Philadelphia Doors & Closets",
    company_picture: "company_blank.png",
    URL: "",
    address: "1841 Norristown Rd.",
    city: "Maple Glen",
    state: "PA",
    zip: "19002",
    phone: "",
    hrs_mf: "",
    hrs_sat: "",
    hrs_sun: "",
    owner: "",
    sales_email: "",
    dealer_emails: "[email protected]",
    google_email: "",
    google_cal_embed: "",
    angies_list: "",
    facebook: "",
    google_plus: "",
    houzz: "",
    yelp: "",
    callrail_id: "-1",
    callrail_company_id: "555380281",
    contractor_num: "",
    subdomain: "philadelphia",
    geo_area: "",
    page_title: "",
    meta_description: "",
    meta_keywords: "",
    meta_geo_position: "",
    meta_geo_placename: "",
    meta_geo_region: "",
    maps_embed: "",
    sm_maps_embed: "",
    corp_ga: "",
    dealer_ga: "",
    min_level_see_sales: 3,
    active: 1,
  },
  {
    id: 27,
    dealer_code: "SC",
    name: "Southern Doors & Closets",
    company_picture: "company_blank.png",
    URL: "carolina.onedaydoorsandclosets.com",
    address: "1200 Woodruff Rd Building D-1, Suite 100.",
    city: "Greenville",
    state: "SC",
    zip: "29607",
    phone: " 864-373-0079",
    hrs_mf: "9:00 am - 5:30 pm",
    hrs_sat: "10:00 am - 4:00 pm",
    hrs_sun: "Available By Appointment",
    owner: "Chris Arnold",
    sales_email: "[email protected]",
    dealer_emails: "[email protected]",
    google_email: "[email protected]",
    google_cal_embed:
      '<iframe src="https://calendar.google.com/calendar/embed?mode=WEEK&amp;height=600&amp;wkst=2&amp;bgcolor=%23FFFFFF&amp;src=inquiry%40onedaycarolina.com&amp;color=%231B887A&amp;src=onedaycarolina.com_c6otg7sj1aegitp76n2hdv7m64%40group.calendar.google.com&amp;color=%23B1440E&amp;ctz=America%2FNew_York" style="border-width:0" width="800" height="600" frameborder="0" scrolling="no"></iframe>',
    angies_list: "",
    facebook: "",
    google_plus: "",
    houzz: "",
    yelp: "",
    callrail_id: "-1",
    callrail_company_id: "-1",
    contractor_num: "",
    subdomain: "carolina",
    geo_area: "Greenville, SC",
    page_title: "Southern Doors & Closets",
    meta_description:
      "Southern Doors & Closets in Greenville offers beautiful Interior Doors, Closet Doors and Closet Organizers, installed in your home with no mess, in just One Day",
    meta_keywords:
      "Southern Doors & Closets, Greenville, SC area, Beautiful Interior Doors, Closet Doors, Closet Organizers, installed in one day",
    meta_geo_position: "34.8482, 82.4035",
    meta_geo_placename: "GREENVILLE, SC",
    meta_geo_region: "SC-US",
    maps_embed:
      '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d837665.074979648!2d-82.4818390673778!3d34.9032070854684!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x88578f6662fa1105%3A0xd8aa9d77bf257696!2sGreenville%2C+SC!5e0!3m2!1sen!2sus!4v1484943807017" width="800" height="600" frameborder="0" style="border:0" allowfullscreen></iframe>',
    sm_maps_embed:
      '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d837665.074979648!2d-82.4818390673778!3d34.9032070854684!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x88578f6662fa1105%3A0xd8aa9d77bf257696!2sGreenville%2C+SC!5e0!3m2!1sen!2sus!4v1484943807017" width="280" height="200" frameborder="0" style="border:0" allowfullscreen></iframe>',
    corp_ga:
      '<!-- Global site tag (gtag.js) - Google Analytics -->n<script async src="https://www.googletagmanager.com/gtag/js?id=UA-75410322-29"></script>n<script>n  window.dataLayer = window.dataLayer || [];n  function gtag(){dataLayer.push(arguments);}n  gtag('js', new Date());nn  gtag('config', 'UA-75410322-29');n</script>nn<script type="text/javascript">n(function(a,e,c,f,g,h,b,d){var k={ak:"862265871",cl:"hqtGCJ_v2nsQj8SUmwM",autoreplace:"864-373-0079"};a[c]=a[c]||function(){(a[c].q=a[c].q||[]).push(arguments)};a[g]||(a[g]=k.ak);b=e.createElement(h);b.async=1;b.src="//www.gstatic.com/wcm/loader.js";d=e.getElementsByTagName(h)[0];d.parentNode.insertBefore(b,d);a[f]=function(b,d,e){a[c](2,b,k,d,null,new Date,e)};a[f]()})(window,document,"_googWcmImpl","_googWcmGet","_googWcmAk","script");n</script>',
    dealer_ga:
      "<!-- Global site tag (gtag.js) - Google Analytics -->n<script async src="https://www.googletagmanager.com/gtag/js?id=UA-112925788-1"></script>n<script>n  window.dataLayer = window.dataLayer || [];n  function gtag(){dataLayer.push(arguments);}n  gtag('js', new Date());nn  gtag('config', 'UA-112925788-1');n</script>n",
    min_level_see_sales: 3,
    active: 1,
  },
];

Essentially, I want to sort through this data, and display the locations grouped by state; something like this on the Warby Parker site:

enter image description here

This means taking this data, grouping it by state, and then mapping through it to display. I’ve used lodash and the groupBy function, and the data is now returning like this:

{
  "CA": [
      {
          "id": 5,
          "dealer_code": "SDC",
          "name": "x Interior Door and Closet Company SD",
          "company_picture": "company_blank.png",
          "URL": "http://sandiegodoorsandclosets.com",
          "address": "123 Doors and Closets Avenue",
          "city": "San Diego",
          "state": "CA",
          "zip": "90122",
          "phone": "858-200-7173",
          "hrs_mf": "",
          "hrs_sat": "",
          "hrs_sun": "",
          "owner": "Glenn Johnson",
          "sales_email": "[email protected]",
          "dealer_emails": "[email protected]",
          "google_email": "[email protected]",
          "google_cal_embed": "<iframe src="https://calendar.google.com/calendar/embed?mode=WEEK&amp;height=600&amp;wkst=1&amp;bgcolor=%23FFFFFF&amp;src=schedule%40cdchq.com&amp;color=%2323164E&amp;src=cdchq.com_03g5gffu5a5gmt5smmcog9f7og%40group.calendar.google.com&amp;color=%23cc209b&amp;src=cdchq.com_hkam4mcg9b67asscst5l082aec%40group.calendar.google.com&amp;color=%23865A5A&amp;src=cdchq.com_91l1rake0pl01ssanh7grm1dk8%40group.calendar.google.com&amp;color=%23B1365F&amp;src=%23contacts%40group.v.calendar.google.com&amp;color=%23865A5A&amp;src=cdchq.com_st6baqemh6l2r43j8unk17pn6g%40group.calendar.google.com&amp;color=%2350ecf8&amp;src=cdchq.com_h9pj9i2o3u41a7soqn25ttoibs%40group.calendar.google.com&amp;color=%23853104&amp;src=cdchq.com_f0nsbsmsfv0vqkvddj690bcn78%40group.calendar.google.com&amp;color=%234a7ee7&amp;src=cdchq.com_981ilh7en0tj26og8qtoqsh3ok%40group.calendar.google.com&amp;color=%23125A12&amp;src=cdchq.com_cmpi7nd7bgf994jq0mfdo97s9c%40group.calendar.google.com&amp;color=%23711616&amp;src=cdchq.com_hpne4fpsse0oneo56btn51tcd8%40group.calendar.google.com&amp;color=%2323b1a7&amp;src=cdchq.com_gfh5o59cot5aglarhdme3a1mpc%40group.calendar.google.com&amp;color=%2323164E&amp;ctz=America%2FLos_Angeles" style="border-width:0" width="800" height="600" frameborder="0" scrolling="no"></iframe>",
          "angies_list": "",
          "facebook": "",
          "google_plus": "",
          "houzz": "",
          "yelp": "",
          "callrail_id": "-1",
          "callrail_company_id": "-1",
          "contractor_num": "",
          "subdomain": "sandiego",
          "geo_area": "San Diego",
          "page_title": "",
          "meta_description": "",
          "meta_keywords": "",
          "meta_geo_position": "",
          "meta_geo_placename": "",
          "meta_geo_region": "",
          "maps_embed": "",
          "sm_maps_embed": "",
          "corp_ga": "",
          "dealer_ga": "",
          "min_level_see_sales": 3,
          "active": 1
      },
  ],
  "CO": [
      {
          "id": 11,
          "dealer_code": "DEN",
          "name": "Denver Doors & Closets",
          "company_picture": "company_blank.png",
          "URL": "http://colorado.onedaydoorsandclosets.com",
          "address": "7300 S Alton Way, Unit F",
          "city": "Centennial",
          "state": "CO",
          "zip": "80112",
          "phone": "303-816-3447",
          "hrs_mf": "8:00 am to 6:00 pm",
          "hrs_sat": "10:00 am to 4:00 pm",
          "hrs_sun": "Closed",
          "owner": "Will Bigler and Kathleen Bigler",
          "sales_email": "[email protected]",
          "dealer_emails": "[email protected]",
          "google_email": "[email protected]",
          "google_cal_embed": "<iframe src="https://calendar.google.com/calendar/embed?mode=WEEK&amp;height=600&amp;wkst=2&amp;bgcolor=%23FFFFFF&amp;src=inquiry%40onedaycolorado.com&amp;color=%231B887A&amp;src=onedaycolorado.com_4ckkptt4l73hgqp82dfftpjmj8%40group.calendar.google.com&amp;color=%23B1365F&amp;src=onedaycolorado.com_1f2jdj02lhf1qd0h7ah4e7f5mg%40group.calendar.google.com&amp;color=%238D6F47&amp;ctz=America%2FDenver" style="border-width:0" width="800" height="600" frameborder="0" scrolling="no"></iframe>",
          "angies_list": "",
          "facebook": "",
          "google_plus": "",
          "houzz": "",
          "yelp": "",
          "callrail_id": "-1",
          "callrail_company_id": "278512782",
          "contractor_num": "",
          "subdomain": "colorado",
          "geo_area": "Denver",
          "page_title": "Denver Doors & Closets",
          "meta_description": "Denver Doors & Closets in Denver Sales Event offers installed interior doors from $159 each, $100 off closet door sets and free installation for closet organizers in Denver, CO 80012",
          "meta_keywords": "Denver Doors & Closets Denver,Installed interior doors from $159, FREE installation for Closet Organizers, Denver, CO 80012",
          "meta_geo_position": "LAT 39.6993 ; LONG -104.8375 ",
          "meta_geo_placename": "DENVER",
          "meta_geo_region": "CO-US",
          "maps_embed": "<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d196281.12937287416!2d-104.9951946882819!3d39.76451867255984!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x876b80aa231f17cf%3A0x118ef4f8278a36d6!2sDenver%2C+CO!5e0!3m2!1sen!2sus!4v1471565161359" width="800" height="600" frameborder="0" style="border:0" allowfullscreen></iframe>",
          "sm_maps_embed": "<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d196281.12937287416!2d-104.9951946882819!3d39.76451867255984!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x876b80aa231f17cf%3A0x118ef4f8278a36d6!2sDenver%2C+CO!5e0!3m2!1sen!2sus!4v1471565161359" width="280" height="200" frameborder="0" style="border:0" allowfullscreen></iframe>",
          "corp_ga": "<!-- Global site tag (gtag.js) - Google Analytics -->n<script async src="https://www.googletagmanager.com/gtag/js?id=UA-75410322-15"></script>n<script>n  window.dataLayer = window.dataLayer || [];n  function gtag(){dataLayer.push(arguments);}n  gtag('js', new Date());nn  gtag('config', 'UA-75410322-15');n</script>n",
          "dealer_ga": "<!-- Global site tag (gtag.js) - Google Analytics -->n<script async src="https://www.googletagmanager.com/gtag/js?id=UA-112907322-1"></script>n<script>n  window.dataLayer = window.dataLayer || [];n  function gtag(){dataLayer.push(arguments);}n  gtag('js', new Date());nn  gtag('config', 'UA-112907322-1');n</script>n",
          "min_level_see_sales": 6,
          "active": 1
      }
  ]
}

So, I’ve got the raw data grouped into new objects by state. However, I’m still struggling to actually map through this data and display it how I need. I tried mutating this data again with

const groups = _.groupBy(locations, 'state');
const locationsByState = Object.entries(groups);

and then mapping through locationsByState, but I’m still not getting what I need, similar to the screenshot posted above. What can I do to iterate through this data?

Thanks.

Answer

Here’s how I got it done:

Like above, I grouped my data by state using lodash:

const groups = _.groupBy(data, 'state');
const locationsByState = Object.entries(groups);

I then map through the locationsByState array, and create a const for the first index in group, which is an array of all locations as sorted by lodash, and then map through that array to return the groups of locations as needed.

{
  locationsByState
    ? locationsByState.map((group, index) => {
        const stateName = group[0];
        const locationByState = group[1];

        return (
          <div className={s.allLocations__region} key={index}>
            <Heading tag="h3" className={s.stateName}>
              {convertRegion(stateName)}
            </Heading>
            <div className={s.allLocations__group}>
              {locationByState.map((dealer, i) => {
                return (
                  <LocationCard
                    key={i}
                    dealer={dealer}
                    className={s.allLocations__location}
                  />
                );
              })}
            </div>
          </div>
        );
      })
    : null;
}

I have various other components and utilities that I’m utilizing here, but I pass the dealer object to my LocationCard component, and display the data there. This works perfectly for what I need.