5

I recently followed a react tutorial to create a template project and have since been modifying code to fit my needs. In particular, there was this piece of code on a component that was passed a parameter called label.

render() {
  const { label } = this.props;
  ...
}

In this example, I returned a JSON object from a controller and passed it to this component using a parameter named rune. A property of the rune JSON is "name", and I wanted to assign the name to a variable called `label. One thing that gave me trouble was the following:

render() {
  console.log("Prop.runes.name: " + this.props.rune.name);
  const { label } = this.props.rune.name;
  console.log("Label: " + label);
  ...
}

The first console.log(...) outputs the name correctly. However, the second log was undefined. After some trial and error, I found that if I removed the curly braces from my const declaration the name resolved properly.

render() {
  const label = this.props.rune.name;
  ...
}

What were the curly braces originally doing? Is there a reason the tutorial initially had them?

devserkan
  • 16,870
  • 4
  • 31
  • 47
BRasmussen
  • 350
  • 2
  • 15

3 Answers3

7

What you ask here is not related to React actually, it is related to Javascript: Destructuring assignment.

For objects, you can destruct a property like that:

const obj = {
  name: "foo",
};

const { name } = obj;
console.log( name );

const name2 = obj.name;
console.log( name2 );

Above, both assignments are equal. First one is the shorthand of the second one.

For your example:

const { label } = this.props.rune.name;

Here, there is a this.props.rune.name.label property and you are destructing it from this.props.rune.name. This is equal to:

const label = this.props.rune.name.label;

not actually

const label = this.props.rune.name;

as you tried.

The related part of React with this syntax is we see it very frequently in React world. Like:

render() {
    const { foo, bar } = this.props;
    const { fizz, buzz } = this.state;
    return (
      <p>A {foo} goes to {bar} and orders a {fizz} without {buzz}</p>; 
    )   
}

or

const AComponent = ( { foo, bar } ) => (
  <p>{foo} loves {bar} in programming world.</p>
);

A caution. When dealing with nested properties to destruct being careful is important. Since as @Tyler Sebastian explained in the comments it is not null safe.

const data = { obj: { name : "foo"} };
const { obj: { name } } = data;

This is OK but if we have a typo there or if we try to use a property which does not exist at that time we get an error since we try to destruct a property from an undefined one.

const data = { obj: { name : "foo"} };
const { objx: { name } } = data;

This throws an error. Thanks to @Tyler Sebastian for the comment.

devserkan
  • 16,870
  • 4
  • 31
  • 47
  • This was an excellent explanation, thank you. For anyone else who wants a deeper reading, nosleepfilipe's answer below has an excellent article on depth destructuring that was also very useful! – BRasmussen Sep 12 '18 at 03:03
  • 1
    You are welcome. You will see destructuring syntax so frequently in React world. When used decently it is very useful. And yes, it is a nice article you mentioned here. There are lots of things we can do using destructuring, some of them are amazing for such a simple syntax :) – devserkan Sep 12 '18 at 03:10
  • 1
    It's worth noting that it's _not_ null safe. `let x = { a: { b: { c: 1 } } }; let { a: { foo: { y } } } = x` will throw. – Tyler Sebastian Sep 13 '18 at 03:35
1

Try with this code

render() {
  console.log("Prop.runes.name: " + this.props.rune.name);
  const label = this.props.rune.name.label;
  console.log("Label: " + label);
  ...
}

You need to declare the variable label without the { }

The curly braces are for Destructuring

You can check here

depth destructuring

  • Yes, I had figured that out! Per my question, I was curious what the curly braces were doing? I see them used elsewhere and they seem to work fine, so I would like to know what was different abut this case. – BRasmussen Sep 12 '18 at 02:50
  • If you console.log( this.props ) you will see that will print a object with multiple keys. If you do let { varname } = this.props it will retrieve a copy of that variable from that object – nosleepfilipe Sep 12 '18 at 02:53
1
let {x} = {a: 10, b: 20, c: 30, d: 40}
console.log(x) // undefined

let {b} = {a: 10, b: 20, c: 30, d: 40}
console.log(b) // 10

console.log(c) // Error: c is not defined

Essentially, const { label } = this.props; is undefined because the object this.props does not have the label property, hence it is unable to match it, as per my x example, but in the b example it does match a property, hence it assigned correctly.

A B
  • 46
  • 1
  • 3
  • Forgot to mention that this is typically seen in React apps, e.g. import React, {Component} from 'react' – A B Sep 12 '18 at 04:09