Easiest list formatting you'll ever use.
Tags: javascript, react
Published: 2022-04-26 16:29:00

---
title: Easiest list formatting you'll ever use.
published: true
description: Using Intl.ListFormat to get around pesky and/or
tags: javascript, react
//cover_image: https://direct_url_to_image.jpg
---

This will be a pretty short post that I hope that many of you find helpful. So we originally had an inelegant solution for dealing with lists as we wanted the ability to dynamically use `<strong>` tags.

```react
// ORIGINAL
export default function ListText({ isBold = false }) {
  const animals = ['Dog', 'Cat', 'Rhino', 'Penguin'];

  return animals.map((animal, index) => {
    const totalAnimals = animals.length;
    const last = index === totalAnimals - 1;
    const comma = !last && totalAnimals > 2;
    const or = totalAnimals >= 2 && last;

    const renderAnimal = isBold ? <strong>{animal}</strong> : animal;

    return (
      <React.Fragment key={index}>
       {or && 'or '}
       {renderAnimal}
       {comma && ','}
       {!last && ' '}
      </React.Fragment>
  })
}
```

> _The above piece of code would render_
> Dog, Cat, Rhino, or Penguin

Because my team was on a tight deadline this piece of code however unsightly was allowed through to production.  To be fair, this code works as expected but I took it upon myself to see if I could find a better solution.

## Intl.ListFormat to the rescue
I encourage you all to read the MDN documentation about [Intl.ListFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat) but essentially it allows you to enable language-sensitive list formatting.  That's right, this will work with any language 🤯

```javascript
export default function ListText({ isBold = false }) {
  const animals = ['Dog', 'Cat', 'Rhino', 'Penguin'];

  return new Intl.ListFormat('en', { style: 'long', type: 'disjunction' })
  .formatToParts(animals)
  .map(({ type, value }) => {
    return type === 'element' && isBold ? <strong>{value}</strong> : value;
  })
}
```

> _The above piece of code would still render_
> Dog, Cat, Rhino, or Penguin

## Let's break this down.
1. We create a new instance of the Intl.ListFormat
2. We set our list format to use English 'en' and set our config to use a style of `'long'` and type of `'disjunction'`.
3. We pass our animals array to the `formatToParts` method which will return us a new array with the _commas_ and _or_ inserted (the length becomes 5)
4. We map through the returned array and check if the type is  an `element`.  The `element` will always coincide with the value from our array where as the type `literal` will be the _comma_ or _or_ respectively.
5. We check if our `isBold` prop is set to `true` and return the value between the `<strong>` tags, otherwise we just pass the value.

## More extensible
Our code is now more extensible.  For example we could pass in an array as one of our props instead of the declared `animals` array.  We could also add a prop to change the `type` in the Intl.ListFormat to allow us to have 'and' instead of 'or'.

## Finishing up
I hope developers running into a similar issue find this to be a bit more useful. You can mess around with the CodePen below.

{% codepen https://codepen.io/agarcia-clarity/pen/rNpbYjo %}