Angular to React | Logo
 

How to Extract Nested Data from Arrays and Objects with One Line of Code Using Destructuring

Are Building something cool that just begging for it's own domain? You can register your own for as low as $0.88/year. Claim your name before squatting domain pirates grab it up and hold it for ransom.

I am not a big fan of javascript one-liners just for the sake of being clever. But, if I can use a one-liner that’s semantically clear, easy to understand and simple to reproduce then I’m all in. That’s how I felt the first time I used a destructuring assignment statment inside a React component.

Let’s Jump into Some Sample Code

Imagine you’re building a React/Redux web app and you have some values nested deeply in your state that you want to access inside the render method of a component. Let’s use this as our sample state:

const sampleState = {
  name: "Michael",
  age: 36,
  location: {
    state: "OK",
    city: "Edmond",
    postal: "73012"
  },
  relatives: {
    wife: {
      name: "Shelley"
    }
  }
}

Now, if I want to get at my wife’s name, it’s nested two levels deep. Of course, I can do something like this:

const wifeName = sampleState.relatives.wife.name

That’s not bad, but what if I also want city, state and age. I’ll have to do this:

const wifeName = sampleState.relatives.wife.name,
      city = sampleState.location.city,
      state = sampleState.location.state,
      age = sampleState.age

The code isn’t bad, but it is unnecessarily verbose. Using destructuring, you could do it all in one line like this:

const { age, location: { city, state }, relatives: { wife: { name } } } = sampleSate

What Exactly is Going on Here?

If you’ve never seen the destructuring assignment syntax before, that probably looks very strange. But let’s take a closer look at what’s happening. For a normal assignment statement in javascript, the variable appears on the left side of the = and the value appears on the right. At first glance, it looks like we have this backwards because there’s all sorts of curly braces on the left side of the =. This is known as object destructuring. Essentially, you are describing to the javascript engine which values you wish to extract from the object on the right side of the =. You can use this same syntaxt to extract just my wife’s name from sampleState like this:

const { relatives: { wife: { name } } } = sampleState

So, on the left side of the assignment, every word that isn’t followed by a : is considered a variable which will be populated with the value of the corresponding key by the same name in the same location of the object on the right side. For example, sampleState has a top-level key called name. I can extract name like this:

const { name } = sampleState

That name variable won’t match the other name key that’s nested inside sampleState.relatives.wife because the left side of the assignment statement must match both key AND location.

Specifying Alias Names for Duplicate Keys

But wait! What if you want to get both name keys in one line? Is that possible? Absolutely! You just need to alias one of them like this:

const { name, relatives: { wife: { name: wifeName } } } = sampleState

Remember that any words not followed by a : are considered variable names. So, words suffixed with a : are helping to define the structure of the object you’re accessing. For variable aliases, you just add a : the the key you wish to access and provide a unique variable name. The following would have also extracted both mine and my wife’s names.

const { name: myName, relatives: { wife: { name: herName } } } = sampleState

Using Destructuring in a React Component

I’ve established a coding convention that requires destructuring inside my React components when accessing this.state or this.props. I always start my class methods with a destructuring assignment clearly describing which pieces of props and state I will need. It is my way of writing self-documenting code.

class SampleComponent extends React.Component {
  render() {
    const { name, age } = this.props
    return (
      <div>
        <strong>{name}:</strong>
        <span>{age}</span>
      </div>
    )
  }
}

Using Destructuring with Arrays

The same type of syntax works with arrays too. Let’s start off with a nice sample array (my apologies in advance to any vegans reading this):

const someArray = [ 'Chicken', 'Fish', 'Beef', 'Lamb' ]

That’s a meaty array. Now, if I want to extract each of these values from the array into unique variables I can do this:

const chicken = someArray[0]
const fish = someArray[1]
const beef = someArray[2]
const lamb = someArray[3]

But, by now you probably realize there’s a simpler way:

const [ chicken, fish, beef, lamb ] = someArray

You can also do fancy things like skip specific elements or slice arrays into pieces like this:

const [ chicken, , , lamb ] = someArray

This assigns chicken='chicken' and lamb='lamb' but skips beef and fish. And for the slicing…

const [ chicken, ...everythingElse ] = someArray

You can guess what this does. chicken='chicken' and everythingElse = ['fish', 'beef', 'lamb']. Not only is it a beautiful one-liner, but it is much simpler to read and comprehend than the equivalent slice statement:

var chicken = someArray[0],
    everythingElse = someArray.slice(1);

Backwards Compatibility and Babel Transpiling

The new destructuring syntax was added to Javascript as part of ES6. That means that not all browsers will support it. If you’re already familiar with ES6 features, you’re probably also familiar with the Babel transpiler. The babel-plugin-transform-es2015-destructuring plugin is the one responsible for converting ES6 Destructuring syntax to backwards-compatible javascript. Let’s use the first example above with sampleState. If we have the following destructuring assignment:

const {
  name,
  age,
  location: { state, city, postal },
  relatives: {
    wife: { name: wifeName }
  }
} = sampleState

Babel will transpile it into this:

var name = someObject.name,
    age = someObject.age,
    _someObject$location = someObject.location,
    state = _someObject$location.state,
    city = _someObject$location.city,
    postal = _someObject$location.postal,
    wifeName = someObject.relatives.wife.name;

Hopefully, after reading this, you now have a new tool in your Javascript belt. Don’t feel like you have to use it just because it is part of ES6. For me, when trying to extract several pieces of nested data from a larger object, the destructuring syntax is usually cleaner and more readable. But, if the same isn’t true in your situation, use what works best – not only for your sake, but for the sake of anyone who has to maintain that codebase in the future.

Are Building something cool that just begging for it's own domain? You can register your own for as low as $0.88/year. Claim your name before squatting domain pirates grab it up and hold it for ransom.
Interested in Writing for Us?

Website developed by Michael Martin  (michael@angulartoreact.com
© 2015-16, All Rights Reserved